2014-12-09 11 views
8

Abbiamo già un sistema in esecuzione che gestisce tutte di connessione-stringhe (DB2, oracolo, MSServer).milioni di inserti: SqlBulkCopy timeout

Attualmente, stiamo usando ExecuteNonQuery() per fare alcuni inserti.

Vogliamo migliorare le prestazioni, utilizzando SqlBulkCopy() anziché ExecuteNonQuery(). Abbiamo alcuni clienti con oltre 50 milioni di record.

Non vogliamo utilizzare SSIS, perché il nostro sistema supporta più database.

Ho creato un progetto di esempio per testare le prestazioni di SqlBulkCopy(). Ho creato una semplice lettura e inserire funzioni per MSServer

Ecco la piccola funzione:

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); 
       } 
      } 
     } 
    } 
} 

Quando ho meno che 200 000 nel mio dummyTable la copia di massa sta lavorando bene. Ma quando sono oltre 200.000 record, ho i seguenti errori:

  • Tentativo di richiamare la copia di massa su un oggetto che ha un'operazione in sospeso.

O

  • L'operazione di attesa scaduta (per l'IDataReader)

ho aumentato la CommandTimeout per il lettore. Sembra che abbia risolto il problema di timeout relativo a IDataReader.

Sto facendo qualcosa di sbagliato nel codice?

+1

Mai mai SqlBulkCopy nella tabella di destinazione. Quella cosa ha seriamente rotto il codice di blocco. Soprattutto quando si utilizza il multi-threading. Crea una tabella temporanea, inseriscila in quella, quindi copia nella tabella di destinazione. – TomTom

+0

Non sto usando la multi-threading. Sto sempre inserendo in un tavolo vuoto. – billybob

+2

Perché sqlbulkcopy? Sul serio. Tabelle sullo stesso database: basta dire al SERVER di copiare i dati invece di caricarli sul tuo programma solo per caricarli. Seleziona direttamente nella tabella di destinazione con una dichiarazione. – TomTom

risposta

9

Potete provare ad aggiungere quanto segue prima della chiamata a WriteToServer ...

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

Non so quale sia la dimensione dei lotti di default o timeout è, ma ho il sospetto che questo potrebbe essere il problema. Speranza che aiuti

Inoltre, puoi provare a giocare con diverse dimensioni di batch per prestazioni ottimali.

0

Si può provare questo

bc.Batch.Size = 100.000; // Numero di righe che si desidera inserire alla volta.

bc.BulkCopyTimeout = 60; // Tempo in secondi, se vuoi tempo di attesa infinito allora assegna 0.

Spero che questo aiuti te e anche altri sviluppatori.