Milioni di inserimenti: timeout SqlBulkCopy

bulkinsert c# sqlbulkcopy sqldatareader sql-server

Domanda

Abbiamo già un sistema in esecuzione che gestisce tutte le stringhe di connessione ( db2 , oracle , MSServer ).

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

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 funzione di lettura e inserimento 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 di 200.000 nel mio dummyTable, la copia bulk funziona 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 IDataReader)

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

Sto facendo qualcosa di sbagliato nel codice?

Risposta accettata

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

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

Non so quale sia la dimensione o il timeout predefinito del lotto, ma sospetto che questo potrebbe essere il tuo problema. Spero possa aiutare

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


Risposta popolare

Puoi provare questo

bc.BatchSize = 100,000; // How many Rows you want to insert at a time
bc.BulkCopyTimeout = 60; // Time in Seconds. If you want infinite waiting Time then assign 0.


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow