DELETE vs TRUNCATE


35

Я намагаюся краще зрозуміти відмінності між командами DELETEта TRUNCATE. Моє розуміння внутрішніх справ щось іде за принципом:

DELETE-> двигун бази даних знаходить і видаляє рядок із відповідних сторінок даних та всіх сторінок індексів, де введено рядок. Таким чином, чим більше індексів, тим довше триває видалення.

TRUNCATE -> просто видаляє всі сторінки даних таблиці масово, що робить це більш ефективним варіантом для видалення вмісту таблиці.

Якщо припустити, що вище сказано правильно (будь ласка, виправте мене, якщо ні):

  1. Як різні режими відновлення впливають на кожне твердження? Якщо взагалі є якийсь ефект
  2. Під час видалення скануються всі індекси чи лише ті, де знаходиться рядок? Я б припустив, що всі індекси відскановані (а не шукаються?)
  3. Як копіюються команди? Чи надсилається та обробляється команда SQL кожному підписчику? Або MSSQL трохи розумніший за це?

2
Існує деяка пов'язана інформація про DELETEта TRUNCATEу відповідях на це питання про корисність TRUNCATE-ing безпосередньо перед a DROP. Ви також можете копатися в журналі, щоб вивчити ефекти обох команд, використовуючи техніку, описану в цій відповіді .
Нік Шамма

1
У цій відповіді відображаються внутрішні операції DELETE та TRUNCATE. Також питання демонструє особливу ситуацію, коли TRUNCATE працює краще.
孔夫子

5
@idstam TRUNCATEможна відкотити . Нік пояснює це у своїй відповіді на питання, яке він пов’язав .
Марк Сторі-Сміт

Для скорочення потрібен дозвіл "змінити таблицю" (у тому сенсі, що усікання є заміною для видалення).
crokusek

Відповіді:


58

DELETE -> движок бази даних знаходить і видаляє рядок із відповідних сторінок даних та всіх сторінок індексів, де введено рядок. Таким чином, чим більше індексів, тим довше триває видалення.

Так, хоча тут є два варіанти. Рядки можуть бути видалені з некластеризованих індексів по рядках тим самим оператором, який виконує видалення базової таблиці. Це відоме як вузький (або за рядком) план оновлення:

Видалення за рядком

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

На видалення індексу

TRUNCATE -> просто видаляє всі сторінки даних таблиці масово, роблячи це більш ефективним варіантом для видалення вмісту таблиці.

Так. TRUNCATE TABLEє більш ефективним з ряду причин:

  1. Можливо, буде потрібно менше замків. Укорочення, як правило, вимагає лише одного блокування модифікації схеми на рівні таблиці (і ексклюзивні блокування в кожному ступені, розміщеному ). Видалення може набувати блокування з нижчою (рядковою чи сторінковою) деталізацією, а також ексклюзивні блокування на будь-яких розміщених сторінках .
  2. Тільки усікання гарантує, що всі сторінки розміщені з маси таблиці. Видалення може залишати порожні сторінки в купі, навіть якщо вказано підказку щодо ексклюзивного блокування таблиці (наприклад, якщо для бази даних увімкнено рівень ізоляції рядкових версій).
  3. Урізання завжди мінімально реєструється (незалежно від використовуваної моделі відновлення). У журналі трансакцій записуються лише операції з розміщення сторінки.
  4. Урізання може використовувати відкладені краплі, якщо об’єкт має 128 розширень або більше. Відкладене падіння означає, що фактична робота щодо розміщення виконується асинхронно фоновим потоком сервера.

Як різні режими відновлення впливають на кожне твердження? Чи взагалі є якийсь ефект?

Видалення завжди повністю реєструється (кожен видалений рядок записується в журнал транзакцій). Існують деякі невеликі відмінності у вмісті записів журналів, якщо модель відновлення відрізняється від інших FULL, але це технічно все-таки повний журнал.

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

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

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

Плани виконання - це конвеєри, орієнтовані на попит: батьківські оператори (ліворуч) спонукають дочірніх операторів виконувати роботу, вимагаючи від них рядків одночасно. Оператори сортування блокують (вони повинні споживати весь вхід, перш ніж створювати перший відсортований рядок), але вони все ще керуються їхнім батьків (Index Delete), вимагаючи цього першого рядка. Видалення індексу одночасно витягує рядок із завершеного сортування, оновлюючи цільовий некластеризований індекс для кожного рядка.

У широкому плані оновлення ви часто бачите стовпці, які оператор оновлення базової таблиці додає до потоку рядків. У цьому випадку кластерне видалення індексу додає до потоку некластеризовані стовпці ключових індексів. Ці дані потрібні механізму зберігання, щоб знайти рядок, який слід видалити з некластеризованого індексу:

Деталі списку вихідних даних

Як копіюються команди? Чи надсилається та обробляється команда SQL кожному підписчику? Або SQL Server трохи розумніший за це?

Урізання не дозволяється на таблиці, що публікується за допомогою транзакційної або злиття реплікації. Спосіб реплікації видалень залежить від типу реплікації та способу її налаштування. Наприклад, реплікація знімків просто повторює перегляд таблиці в часі за допомогою масових методів - додаткові зміни не відслідковуються і не застосовуються. Транзакційна реплікація працює за допомогою зчитування записів журналів та генерування відповідних транзакцій для застосування змін у передплатників. Об'єднання реплікації відстежує зміни за допомогою тригерів та таблиць метаданих.

Пов'язане читання: Оптимізація T-SQL запитів, які змінюють дані

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.