УДАЛИТЬ ПРОТИВ TRUNCATE

35

Я пытаюсь получить более глубокое понимание о различиях между DELETEи TRUNCATEкомандами. Мое понимание внутренних органов идет примерно так:

DELETE-> ядро ​​базы данных находит и удаляет строку из соответствующих страниц данных и всех страниц индекса, где эта строка введена. Таким образом, чем больше индексов, тем больше времени занимает удаление.

TRUNCATE -> просто удаляет все страницы данных таблицы массово, делая это более эффективным вариантом для удаления содержимого таблицы.

Предполагая, что вышеприведенное верно (пожалуйста, исправьте меня, если нет):

  1. Как разные режимы восстановления влияют на каждое утверждение? Если есть какой-либо эффект вообще
  2. При удалении сканируются все индексы или только те, где находится строка? Я бы предположил, что все индексы сканируются (и не ищутся?)
  3. Как реплицируются команды? Отправляется ли и обрабатывается ли команда SQL на каждом подписчике? Или MSSQL немного умнее?
Стюарт Блэклер
источник
2
Существует некоторая сопутствующая информация о DELETEи TRUNCATEв ответах на этот вопрос о полезности TRUNCATEсразу -ную перед DROP. Вы также можете сами покопаться в журнале, чтобы изучить эффекты обеих команд, используя технику, описанную в этом ответе .
Ник Чаммас
1
Этот ответ показывает внутреннюю часть операций DELETE и TRUNCATE. Также вопрос демонстрирует конкретную ситуацию, когда TRUNCATE работает лучше.
孔夫子
5
@idstam TRUNCATEможно откатить. Ник рассказывает об этом в своем ответе на вопрос, который он связал .
Марк Стори-Смит
Для усечения требуется разрешение «изменить таблицу» (в том смысле, что усечение - это замена плагина для удаления).
Crokusek

Ответы:

58

DELETE -> ядро ​​базы данных находит и удаляет строку из соответствующих страниц данных и всех страниц индекса, где эта строка введена. Таким образом, чем больше индексов, тем больше времени занимает удаление.

Да, хотя здесь есть два варианта. Строки могут быть удалены из некластеризованных индексов построчно тем же оператором, который выполняет удаление базовой таблицы. Это называется узким (или для каждой строки) планом обновления:

За удаление строки

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

За удаление индекса

TRUNCATE -> просто массово удаляет все страницы данных таблицы, что делает этот способ более эффективным для удаления содержимого таблицы.

Да. TRUNCATE TABLEявляется более эффективным по ряду причин:

  1. Может понадобиться меньше замков. Усечение обычно требует только одну блокировки модификации схемы на уровне таблицы (и эксклюзивные замки на каждой степени освобождаться). При удалении могут возникать блокировки с более низкой степенью детализации (строки или страницы), а также эксклюзивные блокировки на любых освобожденных страницах .
  2. Только усечение гарантирует, что все страницы освобождаются из таблицы кучи. Удаление может оставить пустые страницы в куче, даже если указана исключительная подсказка блокировки таблицы (например, если для базы данных включен уровень изоляции версий строк).
  3. Усечение всегда минимально регистрируется (независимо от используемой модели восстановления). Только операции освобождения страницы записываются в журнал транзакций.
  4. Усечение может использовать отложенное удаление, если размер объекта составляет 128 экстентов или больше. Отложенное удаление означает, что фактическая работа по освобождению выполняется асинхронно потоком фонового сервера.

Как разные режимы восстановления влияют на каждое утверждение? Есть ли какой-либо эффект вообще?

Удаление всегда полностью регистрируется (каждая удаленная строка записывается в журнал транзакций). Существуют небольшие различия в содержании записей журнала, если модель восстановления отличается от них FULL, но это все еще технически полная запись в журнал.

При удалении сканируются все индексы или только те, где находится строка? Я бы предположил, что все индексы сканируются (и не ищутся?)

Удаление строки в индексе (с использованием узких или широких планов обновления, показанных ранее) - это всегда доступ по ключу (поиск). Сканирование всего индекса для каждой удаленной строки будет ужасно неэффективным. Давайте снова посмотрим на план обновления для индекса, показанный ранее:

Широкий план 2

Планы выполнения представляют собой управляемые спросом конвейеры: родительские операторы (слева) заставляют дочерние операторы выполнять работу, запрашивая у них строку за раз. Операторы сортировки блокируются (они должны использовать весь свой ввод перед созданием первой отсортированной строки), но они все еще управляются своим родителем (удаление индекса), запрашивающим эту первую строку. Удаление индекса извлекает строку за раз из завершенной сортировки, обновляя целевой некластеризованный индекс для каждой строки.

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

Детализация списка вывода

Как реплицируются команды? Отправляется ли и обрабатывается ли команда SQL на каждом подписчике? Или SQL Server немного умнее, чем это?

Усечение не допускается для таблицы, опубликованной с использованием репликации транзакций или репликации слиянием. Способ репликации удалений зависит от типа репликации и ее конфигурации. Например, репликация моментальных снимков просто реплицирует представление таблицы на определенный момент времени с использованием массовых методов - дополнительные изменения не отслеживаются и не применяются. Репликация транзакций работает путем чтения записей журнала и генерации соответствующих транзакций для применения изменений у подписчиков. Репликация слиянием отслеживает изменения с использованием триггеров и таблиц метаданных.

Связанное чтение: Оптимизация запросов T-SQL, которые изменяют данные

Пол Уайт говорит, что GoFundMonica
источник