Чому мої некластеризовані індекси використовують більше місця під час видалення рядків?


22

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

Я написав запит, dm_db_partition_statsщоб повідомити про різницю (після - перед) на сторінках:

дельти dm_db_partition_stats

Індекс 1 - це кластерний індекс, індекс 2 - первинний ключ. Інші некластеризовані та не унікальні.

Чому сторінки збільшуються на цих некластеризованих індексах?
Я очікував, що цифри в гіршому випадку залишаться незмінними.
Я бачу, що лічильники продуктивності повідомляють про збільшення розбиття сторінок під час видалення.

Під час видалення чи повинен привид про перехід на іншу сторінку? Це має відношення до "унікалізаторів"?

Ми в середині розгортання RCSI, але зараз RCSI вимкнено.

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


Лише питання - запустити REORGANIZE на одному з індексів, що виросли, що відбувається? Скільки сторінок видалено? І якщо ви реорганізуєтесь перед видаленням, що відбувається? Я здебільшого думаю, що внутрішні механізми можуть полегшити в деяких випадках виділення цілої нової сторінки та об'єднання, але не очищають порожні сторінки. Я знаю, що REORGANIZE закінчується випаданням значної кількості сторінок навіть на відносно нефрагментованих, але більших індексах.
Сміється Вергілій

Добре запитання @LaughingVergil Коли я отримаю відповідь, я повернусь сюди, щоб повідомити про це. (Але це може зайняти деякий час).
Michael J Swart

У нашому випадку це збільшення було тимчасовим явищем. Маючи достатньо терпіння, прибирання привидів врешті-решт справи зробили свою роботу, і розміри індексів зменшилися.
Michael J Swart

Відповіді:


28

Один з можливих сценаріїв, який дуже мене розважає:

  • Рядки були написані спочатку, коли в базі даних не було ввімкнено зчитуваний знімок (RCSI), ізоляція знімків (SI) або групи доступності (AG)
  • Увімкнено RCSI або SI або базу даних додано в групу доступності
  • Під час видалення до видалених рядків додано 14-байтну часову позначку для підтримки зчитування RCSI / SI / AG

Оскільки цей сервер є первинним в АГ, на нього впливає так само, як і вторинні. Інформація про версію додається на первинному - сторінки даних точно однакові як на праймери, так і в вторинних. Вторинні джерела використовують сховище версій для читання під час оновлення рядків АГ, але вторинні журнали не записують власні версії часової позначки на сторінку. Вони просто успадковують версії від основної роботи.

Щоб продемонструвати зростання, я взяв експорт бази даних Stack Overflow (у якому не ввімкнено RCSI) і створив купу індексів на таблиці повідомлень. Я перевірив розміри індексу за допомогою sp_BlitzIndex @Mode = 2 (скопіювати / вставити в електронну таблицю та трохи очистити, щоб максимально збільшити щільність інформації):

sp_BlitzIndex раніше

Потім я видалив приблизно половину рядків:

BEGIN TRAN;
DELETE dbo.Posts WHERE Id % 2 = 0;
GO

Приємно, поки делети траплялися, файл даних зростав і для розміщення часових міток! Звіт про використання диска SSMS показує події зростання - ось лише верх, щоб проілюструвати:

Події зростання

(Мені подобається демонстрація, де видалення роблять базу даних зростаючою.) Поки видалення працювало, я знову запустив sp_BlitzIndex. Зауважте, що кластерний індекс має менше рядків, але його розмір вже виріс приблизно на 1,5 Гб. Некластеризовані індекси на AcceptedAnswerId різко зросли - вони індексують за малим значенням, яке в основному є нульовим, тому їх розміри індексу майже вдвічі збільшилися!

sp_BlitzIndex під час видалення

Мені не потрібно чекати, коли видалення закінчиться, щоб довести це, тому я зупиню демонстрацію там. Справа в тому, що: коли ви робите великі вилучення на таблиці, яка була реалізована до того, як RCSI, SI або AG були включені, індекси (включаючи кластеризовані) можуть насправді зростати, щоб вмістити додавання часової мітки магазину версій.


3
Це пояснення. Виявляється, є й інші обставини, які можуть призвести до відсутності 14 версій байтів. У моєму тестуванні здається, що відновлення індексу в режимі офлайн відновить рядки без байтів версії.
Michael J Swart
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.