Миллион вложений: тайм-аут SqlBulkCopy

У нас уже есть работающая система, которая обрабатывает все строки соединения (db2, oracle, MSServer).

В настоящее время мы используем ExecuteNonQuery() для создания некоторых вставок.

Мы хотим улучшить производительность, используя SqlBulkCopy() вместо ExecuteNonQuery(). У нас есть несколько клиентов, у которых более 50 миллионов записей.

Мы не хотим использовать SSIS, потому что наша система поддерживает несколько баз данных.

Я создал образец проекта для проверки производительности SqlBulkCopy(). Я создал простую функцию чтения и вставки для MSServer

Здесь малая функция:

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

Когда у меня меньше 200 000 в моей манекене, массовая копия работает нормально. Но, когда у него более 200 000 записей, у меня есть следующие ошибки:

  • Попытка вызвать массовую копию объекта, который имеет ожидающую операцию.

ИЛИ

  • Ожидаемая операция ожидания (для IDataReader)

Я увеличил CommandTimeout для читателя. Похоже, что он решил проблему с таймаутом, связанную с IDataReader.

Я делаю что-то неправильно в коде?

Ответ 1

Можете ли вы попробовать добавить следующее перед вызовом WriteToServer...

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

Я не знаю, что такое размер или время ожидания по умолчанию, но я подозреваю, что это может быть вашей проблемой. Надеюсь, что поможет

Кроме того, вы можете попробовать играть с различными размерами партий для оптимальной производительности.

Ответ 2

Вы можете попробовать это

bc.BatchSize = 100000; // 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.