2010-04-12 1 views
8

Я тестирую скорость вставки нескольких строк с помощью одного оператора INSERT.Несколько строк с одним INSERT в SQLServer 2008

Например: INSERT INTO [MyTable] VALUES (5, 'собака'), (6, 'кошка'), (3, «рыбы)

Это очень быстро, пока я не пройди 50 строк на одно утверждение, то скорость значительно падает.

Вставка 10000 рядов с партиями из 50 единиц занимает 0,9 секунды. Вставка 10000 строк с партиями из 51 занимает 5,7 секунды.

Мой вопрос состоит из двух частей:

  1. Почему такой жесткий падение производительности на 50?
  2. Могу ли я полагаться на это поведение и кодировать свое приложение, чтобы никогда не отправлять партии более 50?

Мои тесты были выполнены в C++ и ADO.

Редактировать: Похоже, что выпадающая точка не 50 строк, а 1000 столбцов. Я получаю аналогичные результаты с 50 строками из 20 столбцов или 100 строк из 10 столбцов.

+0

У меня такое ощущение, что он ухудшается из-за разбора ввода. – Andrey

+2

Полная и полная дикая догадка: менее 50 строк кэшируются в ОЗУ с помощью SQL Server, но большие вставки считаются более «важными» и немедленно выписываются на диск. Честно говоря, не уверен (поэтому комментарий, а не ответ) –

ответ

0

Вы сравнили этот товар с аналогичным соединением? http://blog.sqlauthority.com/2007/06/08/sql-server-insert-multiple-records-using-one-insert-statement-use-of-union-all/

Я подозреваю, что есть внутренний кэш/индекс, который используется до 50 строк (это хорошее округлое десятичное число). После 50 строк он возвращается к менее эффективному алгоритму вставки общего случая, который может обрабатывать произвольные количества входов без использования чрезмерной памяти.

+0

Просто попробовал подход UNION ALL. Это также довольно медленно. Около 7 секунд для 10000 строк. – Todd

0

замедление, вероятно, синтаксический анализ строковых значений: VALUES (5, 'dog'), (6, 'cat'), (3, 'fish), а не проблема INSERT.

попробовать что-то вроде этого, который будет вставлять одну строку для каждой строки, возвращаемой запросом:

INSERT INTO YourTable1 
    (col1, col2) 
    SELECT 
     Value1, Value2 
     FROM YourTable2 
     WHERE ...--rows will be more than 50 

и посмотреть, что происходит

0

Если вы используете SQL 2008, то вы можете использовать табличное значение параметры и просто сделать один оператор insert.

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

+0

Я пробовал это, и как новичок SQL, я не уверен, что делаю это самым оптимальным способом. Однако мои тесты показывают от 6 секунд до 30 секунд на 10000 строк, в зависимости от размера партии. Ничто не близко к многострочным операторам INSERT. – Todd

+0

Это очень странно. Вы назначаете все поля в таблице или некоторые из них назначаются через значения по умолчанию столбца? Если позже, они могут стать дорогими (например, функция getdate()) ... – NotMe

+0

Я следовал примеру здесь: http://msdn.microsoft.com/en-us/library/bb510489%28SQL.100%29. aspx Но вместо того, чтобы вставлять во временную таблицу из другой таблицы, я вставляю значения с помощью многострочной вставки. Я указываю все значения, никаких значений по умолчанию. – Todd

0

Случайные мысли:

  • является она полностью соответствует при запуске повторно?
  • Вы проверяете дубликаты в 1-м строках 10k для второй вставки 10k?
  • Вы сначала попробовали размер партии 51?
  • Вы лишили таблицу между тестами?
+0

Да, это очень непротиворечиво. И я делаю пустой стол между каждым тестом. – Todd

+0

@Todd: интересно. Хороший вопрос. И у меня нет дальнейших идей, хотя :-) – gbn

2

Он также может быть связан с размером строки. Таблица, которую вы используете в качестве примера, кажется, имеет только 2 столбца. Что, если у него 25 столбцов? Выпускается ли производительность также на 50 строк?

+0

Интересно. Приведенная выше таблица была всего лишь примером, моя фактическая таблица имеет в ней 20 столбцов. Я сократил до 10 и попытался снова. Теперь я получаю отрезок на 100. Партии 100 занимают около 0,6 секунды. Партии 101 занимают около 3,25 секунды. Похоже, что предел не 50 строк, а 1000 отдельных обновленных полей? – Todd

+0

Похоже, что обрезание больше похоже на тотальные данные в памяти. Если таблица небольшая, то, возможно, вы можете поместить 100 строк в «блок», независимо от того, какой блок. Но большие таблицы со многими столбцами или с несколькими большими столбцами (например, VARCHAR (1200)) ограничивают количество строк, которые вы могли бы поместить в блок. – MJB

0

Для высокообъемных и высокочастотных вставок рассмотрите возможность использования Bulk Inserts для загрузки ваших данных. Не самая простая вещь, которую должен реализовать мир, и это приносит с собой новый набор проблем, но это может быть намного быстрее, чем выполнение INSERT.