Массовая вставка в сервер SQL - PullRequest
16 голосов
/ 02 декабря 2008

Я пытаюсь вставить массу записей в SQL Server 2005 из Vb.Net. Хотя вставка работает нормально, я прилагаю все усилия, чтобы сделать это как можно быстрее. В настоящее время для 100 000 записей требуется ~ 11 минут. Каков будет предложенный подход для вставки большого количества записей в SQL Server из приложения?

Мой текущий apporach в основном открывает соединение, перебирает мой список информации и запускает отдельные SQL-вставки, а затем закрывает соединение. У кого-нибудь есть лучшее предложение о том, как это сделать?

Текущая функция:

Public Sub BatchInsert(ByVal ParamCollections As List(Of SqlParameter()))

    Dim Conn As SqlConnection = New SqlConnection(DBHelper.DatabaseConnection)
    Using scope As TransactionScope = New TransactionScope()
    Using Conn

        Dim cmd As SqlCommand = New SqlCommand("sproc_name", Conn)

        Conn.Open()
        cmd.CommandType = CommandType.StoredProcedure

        For i = 0 To ParamCollections.Count - 1

            cmd.Parameters.Clear()
            cmd.Parameters.AddRange(ParamCollections(i))
            cmd.ExecuteNonQuery()

        Next

        Conn.Close()
        scope.Complete()
    End Using
    End Using

End Sub

Ответы [ 6 ]

20 голосов
/ 02 декабря 2008

Используйте класс SqlBulkCopy , он сможет проходить через эти 100К строк гораздо быстрее, чем отдельные вставки.

О, и если вы можете, я бы настоятельно рекомендовал вам реализовать класс IDataReader для подачи в SqlBulkCopy.WriteToServer (IDataReader) метод, который позволит вам производить данные последовательно, по одной строке за раз. Если вы, например, импортируете из текстового файла, создайте несколько методов IEnumerable<T>, использующих yield return, и преобразуйте их в объект IDataReader , что позволит вам очень естественно передавать данные на сервер.

Чтобы противостоять потере возможности отката с помощью BCP, вы можете перенести данные во временную таблицу, а затем выполнить обычные операторы INSERT INTO на сервере, массово перенеся данные из временной таблицы в рабочую таблицу, это позволит вам использовать транзакцию для последней части переноса и все равно будет выполняться намного быстрее, чем ваши исходные отдельные операторы вставки.

РЕДАКТИРОВАТЬ: и Вот пример (C #, но должно быть легко преобразовать в VB.Net) использования API массовой загрузки.

11 голосов
/ 02 декабря 2008

Благодаря всеобщей помощи я смог выполнить свою задачу. SQLBulkCopy идеально подходит для моих нужд (хотя были и другие отличные предложения). Используя SqlBulkcopy, время возросло с 11 минут до 45 секунд. Я не могу поверить в разницу!

Для дальнейшего использования, вот несколько бит информации:

  • Чтобы использовать SQL Bulk Copy, ваши данные должны быть в форме DataSet, DataReader или DataTable. Некоторый XML также разрешен.

Базовый код реализации:

    Public Sub PerformBulkCopy(ByVal dt As DataTable)

    Using Conn As SqlConnection = New SqlConnection(DBHelper.DatabaseConnection)
        Conn.Open()

        Using s As SqlBulkCopy = New SqlBulkCopy(Conn)

            s.DestinationTableName = "TableName"
            s.WriteToServer(dt)
            s.Close()

        End Using

        Conn.Close()
    End Using
End Sub

Очень информативная ссылка, которую я нашел:

Использование Sql Bulk Copy

Спасибо всем за помощь! Я искренне ценю это.

2 голосов
/ 02 декабря 2008

Вот несколько сравнений скорости различных методов импорта текстовых файлов на сервер SQL: http://weblogs.sqlteam.com/mladenp/archive/2006/07/22/10742.aspx

надеюсь, это поможет.

2 голосов
/ 02 декабря 2008

Поместите свои данные для импорта в CSV-файл и запустите утилиту bcp для данных. Вы не можете получить больше скорости при последовательных вызовах, вставляющих по одной строке за раз, вам, безусловно, нужна массовая утилита, если вам нужна производительность.

Класс SQLBulkCopy позволит вам передавать все данные в коллекции, чтобы сервер мог обрабатывать все сразу, исключая взад и вперед. Так что, если вы хотите избежать создания временных файлов (что я и сделал бы), посмотрите на этот класс.

Просто оставить соединение открытым - это хорошее начало, но у вас все еще есть накладные расходы, связанные с отправкой строки, сохранением SQL, возвращением результата, а затем вы должны выполнить итерацию до следующей строки.

1 голос
/ 02 декабря 2008

Есть также сохраненный процесс (называемый Bulk Insert), который поможет вам. Он использует bcp под крышками.

проверьте эту ссылку, чтобы увидеть синтаксис

текст ссылки

0 голосов
/ 02 декабря 2008

Зависит от того, как реализован класс массового копирования. Но есть инструмент командной строки, включенный в установки SQL Server, который делает именно это (вероятно, то же самое). Это называется "BCP". Я использую его прямо сейчас, и он сможет пробиться через 100 тыс. Строк за считанные секунды.

В документации MSDN эта утилита называется "массовый импорт".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...