SQL Server - объединение больших таблиц без блокировки данных - PullRequest
9 голосов
/ 21 июля 2010

У меня есть очень большой набор данных (~ 3 миллиона записей), который необходимо объединять с обновлениями и новыми записями по ежедневному расписанию.У меня есть хранимая процедура, которая фактически разбивает набор записей на 1000 блоков записей и использует команду MERGE с временными таблицами, чтобы избежать блокировки действующей таблицы во время обновления данных.Проблема в том, что это не совсем помогает.Таблица по-прежнему «блокируется», и наш веб-сайт, который использует данные, получает тайм-ауты при попытке доступа к данным.Я даже попытался разделить его на 100 записей и даже попытался WAITFOR DELAY '000:00:5', чтобы посмотреть, поможет ли это сделать паузу между объединением фрагментов.Это все еще довольно вяло.

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

Спасибо

Ответы [ 3 ]

6 голосов
/ 21 июля 2010

Измените свой интерфейс, чтобы использовать NOLOCK или READ UNCOMMITTED, когда выбирает .

Вы не можете NOLOCK MERGE, INSERT или UPDATE, так как записи должны быть заблокированы, чтобывыполнить обновление.Однако вы можете ОТМЕНИТЬ ВЫБОРЫ.

Обратите внимание, что вы должны использовать это с осторожностью.Если грязные чтения в порядке, тогда продолжайте.Однако, если для чтения требуются обновленные данные, вам нужно пойти другим путем и выяснить, почему объединение записей 3M вызывает проблему.

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

В идеале было бы достаточно оперативной памяти, чтобы вытянуть всю базу данных в память по мере необходимости.Например, если у вас есть база данных 4 ГБ, убедитесь, что у вас 8 ГБ ОЗУ .. на сервере x64, конечно.

5 голосов
/ 29 июня 2012

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

Когда мы объединили записи исходной таблицы по всему рабочему окну, а затем выполнили MERGE только один раз, мы увидели увеличение производительности на 500%.Я объясняю это тем, что вы платите за предварительный анализ команды MERGE только один раз, а не снова и снова в тесном цикле.

Более того, я уверен, что объединение 1,6 миллиона строк (источник)на 7 миллионов строк (цель), в отличие от 400 строк на 7 миллионов строк при более чем 4000 различных операциях (в нашем случае) намного лучше использует возможности механизма SQL-сервера.Опять же, значительный объем работы заключается в анализе двух наборов данных, и это делается только один раз.

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

http://msdn.microsoft.com/en-us/library/cc879317(v=SQL.100).aspx

0 голосов
/ 09 марта 2017

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

Например: у нас была таблица, для которой INSERT занимал сумасшедшие 0,2 секунды на запись, большинствоэтого времени, казалось бы, было потрачено впустую на фиксацию транзакции, поэтому мы переключили это на использование MERGE, и некоторые быстрые тесты показали, что это позволило нам вставить 256 записей за 0,4 секунды или даже 512 за 0,5 секунды, мы проверили это с генераторами нагрузки, и все казалосьвсе будет в порядке, пока не произойдет попадание в производство, и все блокируется в ад на блокировках страницы, что приведет к гораздо более низкой общей пропускной способности, чем с отдельными INSERT.

Решение было в том, чтобы не только группировать записи от одного производителяв операции MERGE, но также для пакетной обработки от производителей, отправляющихся к отдельной БД, в одной операции MERGE через дополнительный уровень очереди (ранее также одно соединение на БД, но с использованием MARS для чередования всех вызовов производителей к хранимой процедуределафактической транзакции MERGE), таким образом, мы смогли без проблем обрабатывать многие тысячи INSERT в секунду.

Обязательно иметь подсказки NOLOCK для всех ваших операций чтения с внешнего интерфейса, всегда.

...