2009-07-29 3 views
6

Я хочу вставить n записей в одну таблицу. Может быть много одновременных пользователей, и они могут вставлять/обновлять/выбирать данные из этой таблицы. Что лучше вставить в такую ​​таблицу, скажем 1000 записей:Производительность запроса вставки Sql

  1. Отправить один запрос sql к базе данных с несколькими вставками. Это экономит сервер на вызовы базы данных, но (я не уверен) блокирует таблицу до тех пор, пока вставка не будет завершена, и все остальные запросы к этой таблице будут ждать.
  2. Разделите 1000 записей в некоторых кусках и отправьте их в несколько запросов sql. Это позволяет выполнять другие запросы в таблице, но тратит время на вызовы сервера на базу.

Это зависит от чего-то, или существует единственный способ, который всегда является оптимальным? Это зависит от того, используются ли транзакции или нет, при вставке данных? Есть ли еще лучшие способы выполнения такой вставки?

База данных, которую я использую, - это MS SQL, но интересно, как она работает в других БД, таких как Oracle.

ответ

6

Это полностью зависит от того, что вы используете RDBMS.

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

В SQL Server записи блокируют чтение по затронутым строкам/страницам/таблицам (в зависимости от проблем с эскалацией блокировки), если вы не установили TRANSACTION ISOLATION LEVEL в SNAPSHOT.

Во всех транзакционных механизмах, допускающих одновременную запись и чтение, движок должен хранить как старые, так и новые данные где-то, чтобы он был доступен одновременно.

В Oracle старые данные копируются в табличное пространство UNDO.

В SQL Server он копируется в tempdb (только если включена защита SNAPSHOT, в противном случае она просто заблокирована).

Для этого всегда требуются ресурсы (память или диск), и вы можете исчерпать эти ресурсы, если ваш запрос UPDATE влияет на множество строк.

1

Установить уровень изоляции (параллелизма), который позволяет считывать старые данные во время транзакции - например, В SQL Server 2005+ есть READ SNAPSHOT.

2

Я писал об этом a while ago - Я думаю, что сообщение отвечает на некоторые из ваших вопросов. Рекомендация CK звучит (и, как и Quassnoi-, он имеет некоторые хорошие моменты в отношении Oracle), если вы беспокоитесь о том, что читатели блокируют авторов.

+0

интересный пост в блоге +1. Меня интересует, что транзакции _reason_ появляются быстрее в вашем тесте. Я подозреваю, что это связано с тем, что многие из необходимых замков уже были сделаны с помощью предыдущих проходов. Однако одна важная вещь, что ваш пост не касается, - это поведение под нагрузкой. Ваши тесты кажутся изолированными; в живой системе я подозреваю, что результаты будут инвертироваться довольно быстро. – EBarr

2

Общее правило заключается в том, что вы должны дать базе данных понять, как выполнить эту работу. Это работает лучше, чем больше вы говорите, чтобы делать это в одном утверждении, то есть вы должны вставить 1000 записей за один раз. Это лучше всего подходит для . Большинство серверов базы данных и большинство серверов не блокируют чтение для записи.

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

Взаимосвязанный способ заключается в отправке нескольких команд вставки, например, 10 или 100 строк с фиксацией между ними в одном большом скрипте на сервере.

Добавлено: Большинство серверов баз данных не блокируют чтение, как в Oracle, IBM DB/2 и MySQl, используя таблицы InnoDB. SQL Server, с другой стороны, удается блокировать таблицы даже для чтения и не входит в их число.

+1

Я думаю, вы обнаружите, что большинство БД имеют проблемы, когда читатели блокируют писателей (Oracle не делает). – RichardOD

+0

Ссылка на базовую станцию ​​Microsoft ADO.NET рекомендует использовать размер партии от 100 до 1000. – RichardOD

+0

@RichardOD: Не могли бы вы разместить ссылку на эту рекомендацию? – Kamarey