2014-12-09 7 views
8

Wir haben bereits ein laufendes System, das alle Verbindungs-strings (db2, Orakel, MSServer) behandelt.Million Einsätze: SqlBulkCopy Timeout

Derzeit verwenden wir ExecuteNonQuery(), um einige Einsätze zu machen.

Wir wollen die Leistung verbessern, indem wir SqlBulkCopy() anstelle von ExecuteNonQuery() verwenden. Wir haben einige Kunden, die mehr als 50 Millionen Datensätze haben.

Wir möchten nicht SSIS verwenden, weil unser System mehrere Datenbanken unterstützt.

Ich erstellte ein Beispielprojekt, um die Leistung von SqlBulkCopy() zu testen. Ich habe eine einfache Lese- und Einfügen-Funktion für MSServer

Hier ist die kleine Funktion:

public void insertIntoSQLServer() 
{ 
    using (SqlConnection SourceConnection = new SqlConnection(_sourceConnectionString)) 
    { 
     //Open the connection to get the data from the source table 
     SourceConnection.Open(); 
     using (SqlCommand command = new SqlCommand("select * from " + _sourceSchemaName + "." + _sourceTableName + ";", SourceConnection)) 
     { 
      //Read from the source table 
      command.CommandTimeout = 2400; 
      SqlDataReader reader = command.ExecuteReader(); 

      using (SqlConnection DestinationConnection = new SqlConnection(_destinationConnectionString)) 
      { 
       DestinationConnection.Open(); 
       //Clean the destination table 
       new SqlCommand("delete from " + _destinationSchemaName + "." + _destinationTableName + ";", DestinationConnection).ExecuteNonQuery(); 

       using (SqlBulkCopy bc = new SqlBulkCopy(DestinationConnection)) 
       { 
        bc.DestinationTableName = string.Format("[{0}].[{1}]", _destinationSchemaName, _destinationTableName); 
        bc.NotifyAfter = 10000; 
        //bc.SqlRowsCopied += bc_SqlRowsCopied; 
        bc.WriteToServer(reader); 
       } 
      } 
     } 
    } 
} 

Wenn ich weniger haben, dass 200 000 in meinem dummyTable die Massenkopie funktioniert gut. Aber, wenn es mehr als 200 000 Datensätze ist, habe ich die folgenden Fehler:

  • Versuch auf ein Objekt Massenkopie aufzurufen, die eine ausstehende Operation hat.

OR

  • Die Warteoperation timed out (für die IDataReader)

I die Command für den Leser erhöht. Es scheint, dass es das Timeout-Problem im Zusammenhang mit IDataReader gelöst hat.

Mache ich etwas falsch im Code?

+1

Niemals SqlBulkCopy in die Zieltabelle. Das Ding hat den Sperrcode ernsthaft gebrochen. Besonders bei Verwendung von Multi-Threading. Erstellen Sie eine temporäre Tabelle, fügen Sie sie in die Tabelle ein und kopieren Sie sie in die Zieltabelle. – TomTom

+0

Ich verwende kein Multi-Threading. Ich füge immer in einen leeren Tisch ein. – billybob

+2

Warum sqlbulkcopy überhaupt? Ernst. Tabellen in der gleichen Datenbank - Sagen Sie dem SERVER einfach, die Daten zu kopieren, anstatt sie in Ihr Programm zu ziehen, nur um sie hochzuladen. Wählen Sie mit einer Anweisung direkt in die Zieltabelle. – TomTom

Antwort

9

Können Sie versuchen Sie, die folgenden vor dem Aufruf von WriteToServer ...

bc.BatchSize = 10000; 
bc.BulkCopyTimeout = 0; 

Ich weiß nicht, was die Standard-Chargengröße oder Timeout, aber ich vermute, das Ihr Problem sein könnte. Hoffe, dass hilft

Auch können Sie versuchen, mit verschiedenen Batch-Größen für optimale Leistung zu spielen.

0

Sie können versuchen, diese

bc.BatchSize = 100.000; // Wie viele Zeilen möchten Sie gleichzeitig einfügen?

bc.BulkCopyTimeout = 60; // Zeit in Sekunden, Wenn Sie eine unendliche Wartezeit haben wollen, dann vergeben Sie 0.

Ich hoffe, dies hilft Ihnen und anderen Entwicklern auch.