Улучшить скорость удаления для SQL Server


12

У нас огромная производственная база данных, ее размер составляет около 300 ГБ. Есть ли какой-либо подход к улучшению производительности запроса на удаление? Сейчас скорость удаления составляет от 1 до 10 тысяч в минуту, это очень медленно для нас.


2
1000 строк в минуту звучит очень медленно. Вы испытываете блокировку? Или это слишком медленно, чтобы выбрать строки, что указывает на необходимость индекса?
Джеймс Z

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

6
Недостаточно деталей, чтобы дать ответ. Какой запрос вы выполняете? Есть ли у вас индексы по задействованным столбцам критериев (если есть)? У вас есть триггеры на удаление? ...
Себастьян Севрин

3
Вы пытаетесь удалить миллиард строк одновременно? Возможно ли, что вы ждете автостраду после автостраницы после автостраницы? (Более чем вероятно, что вы ожидаете активности журнала, а не фактической операции удаления.) См. Эту статью ...
Аарон Бертран

3
Также. Есть ли ограничения по внешнему ключу? Пожалуйста, предоставьте полное определение таблицы, запрос и план выполнения.
Мартин Смит,

Ответы:


20

Если вы пытаетесь удалить большое количество строк в одном операторе, вероятно, вы ожидаете активности журнала. Так что вы можете:

  1. Убедитесь, что ваш журнал имеет соответствующий размер, чтобы события роста не замедляли вас. С настройками по умолчанию ваш журнал, вероятно, начинается с 1 МБ с 10% роста. События роста стоят дорого, и если вы регистрируете даже 10 ГБ удалений, это снизит производительность не только сейчас, но и в будущем (из-за того, что это делает с VLF).
  2. При удалении всей таблицы, использование TRUNCATEили DROP/ CREATE.
  3. Если вы удаляете большую часть таблицы, используйте, SELECT INTOчтобы поместить данные, которые вы хотите сохранить, в другую таблицу, а TRUNCATEзатем переместите небольшую часть назад. (Или просто удалите старую таблицу, переименуйте новую и повторно примените ограничения / разрешения и т. Д.)
  4. Сведите к минимуму влияние ведения журнала, прежде всего, удаляя данные порциями вместо всех сразу. Смотрите эту статью . Вы также можете временно переключиться на простое восстановление, так что вам нужно только CHECKPOINTочистить журнал вместо того, чтобы делать резервные копии журналов, но вы должны быть уверены, что вернули его обратно и создали новую полную резервную копию, чтобы заново инициировать цепочку журналов. ,

+1, от меня за отличную статью. В прошлом это помогло мне понять, как наши разработчики понимают операцию удаления, когда они просто обращаются к нам за медлительностью и ростом файла журнала.
KASQLDBA

Также, если есть какие-либо ненужные индексы, удаление их увеличит скорость удаления. Опять же, если вы удалите все или почти все данные, сначала удалитесь все индексы, а затем создадите их снова.
Тони Хинкль

3
@ Тони, выбрасывающий индекс, также должен быть зарегистрирован (как и его создание), поэтому может возникнуть вопрос, когда вы захотите оплатить эту стоимость. Без тестирования я не уверен, что для сценария удаления есть огромное преимущество (как было бы для вставки / обновления), если у вас нет индексов, которые вы не собираетесь хранить позже.
Аарон Бертран

Может ли временное отключение ограничений FK улучшить запрос?
Лев З

3

Есть подсказка, но какую версию вы используете? Это корпоративная версия? Так или иначе:

  1. Если вы можете переместить журнал транзакций на более быстрый диск
  2. Проанализируйте где . Будет ли он использовать индекс для идентификации удаляемых записей? Если нет, можете ли вы добавить индекс?
  3. У вас есть какой-нибудь индекс в таблице, который вы можете удалить? Если да, отбросьте их.
  4. У вас есть внешние ключи против этой таблицы? Это действительно может замедлить ваше удаление.
  5. Если у вас корпоративная версия и узким местом является дисковый ввод-вывод, сжатие на уровне строк может вам немного помочь (или нет, в зависимости от ваших данных)
  6. Вы можете разделить таблицу? Локальные индексы и отбрасывание разделов могут быть быстрее.
  7. Изучите узкое место с помощью монитора активности.

Добавьте детали, когда вы работаете с большой базой данных, нет единого правильного ответа.


0

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

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

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


0

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

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


это был точно мой случай. Это немного рискованно отключить contraint, но удаление пошел с 1 ряда / seocnd 500 / второй
Jurion

0

Добавляя еще несколько пунктов ...

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

Чтобы получить дополнительную помощь, опубликуйте запрос, который вы используете, информацию о таблице и любую информацию о блокировке.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.