відновити кластерний індекс, чому розмір даних зменшується?


10

Коли ми проводили перебудову на кластерному індексі таблиці, в якій є близько 15 Гб даних, і розмір даних зменшився до 5 ГБ, як це може бути? Які "дані" видаляються?

Розмір даних я маю на увазі стовпець "дані" DBCC sp_spaceused

Перед відновленням кластерного індексу:

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    39169656 KB 15857960 KB 22916496 KB 395200 KB

Після відновлення кластерного індексу:

name                  rows        reserved    data        index_size  unused
LEDGERJOURNALTRANS    43583730    29076736 KB 5867048 KB  22880144 KB 329544 KB

TSQL для відновлення:

USE [DAX5TEST]
GO
ALTER INDEX [I_212RECID] ON [dbo].[LEDGERJOURNALTRANS] REBUILD PARTITION = ALL WITH ( PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, ONLINE = ON, SORT_IN_TEMPDB = OFF, DATA_COMPRESSION = PAGE, FILLFACTOR = 85 )
GO

Ви визначаєте розмір даних за розміром файлу?
JNK

Розмір даних я маю на увазі стовпець "дані" DBCC sp_spaceused
Даніель Бьорк,

Це був би стовпець "дані" EXEC sp_spaceused.
RLF

1
Чи пропустив кожен орган, що ОП використовує стиснення сторінки = увімкнено у своєму сценарії відновлення, і я думаю, це не було раніше. Даніель, ти можеш підтвердити?
Шанки

1
@Shanky: Це ALTER INDEXтвердження виглядає так, що він був створений кодом (оскільки він містить купу опцій у налаштуваннях за замовчуванням), тому я підозрюю, що він був побудований з існуючих параметрів індексу. Але ви маєте рацію: якщо стиснення не було включене в кластерному індексі до цього запуску, це однозначно пояснить більшість скорочень сліду даних. (знову: Даніель, ти міг би підтвердити так чи інакше?)
Девід Спіллетт

Відповіді:


16

Якщо у таблиці є кластерний індекс, індекс - це дані таблиці (інакше у вас є таблиця типу купи). Перебудова кластерного індексу (фактично будь-який індекс, але простір не вважатиметься "даними" для некластеризованого індексу) призведе до об'єднання частково використаних сторінок у більш повну форму.

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

Також видалення може призвести до часткових сторінок. Якщо ви видалите всі рядки на сторінці, вона вважається "невикористаною", але якщо в ній залишився один чи більше рядків даних, вони все ще вважаються як використовувані. Навіть якщо на сторінці є лише один рядок, що використовує 10 байт, ця сторінка вважається 8192 байтом у кількості використовуваного місця. Знову майбутні вставки можуть заповнити частину прогалини.

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

SQL Server не витрачає часу, намагаючись нормалізувати дані, переставляючи способи використання сторінок, поки не буде чітко сказано такому, як ваш порядок перебудови індексу, оскільки такі вправи зі збору сміття можуть бути кошмаром продуктивності.

Я підозрюю, що це ви бачите, хоча я б сказав, що виділення достатньої кількості місця для приблизно 2,7-кратного обсягу даних, які абсолютно потрібні, - це дуже поганий випадок. Це може означати, що у вас є щось випадкове як одна із значущих клавіш індексу (можливо, стовпець UUID), що означає, що нові рядки навряд чи будуть додані в порядку індексу, та / або що нещодавно відбулося значне число видалень.

Приклад розділення сторінки

Вставка в порядку індексу з рядками фіксованої довжини, з яких чотири розміщуються на сторінці:

Start with one empty page: 
        [__|__|__|__]
Add the first item in index order:
        [00|__|__|__]
Add the next three
        [00|02|04|06]
Adding the next will result in a new page:
        [00|02|04|06] [08|__|__|__]
And so on...
        [00|02|04|06] [08|10|12|14] [16|18|__|__]

Тепер для додавання рядків із порядку індексу (саме тому я використовував парні числа лише вище): додавання 11означатиме або розширення другої сторінки (не можливо, оскільки вони мають фіксований розмір), переміщення всього вище 11 вгору на одну (занадто дорого на великий індекс) або розділення сторінки так:

[00|02|04|06] [08|10|11|__] [12|14|__|__] [16|18|__|__]

З цього моменту додавання 13і 17не призведе до розколу, оскільки наразі є місце на відповідних сторінках:

[00|02|04|06] [08|10|11|__] [12|13|14|__] [16|17|18|__]

але додавання 03 буде:

[00|02|03|__] [04|06|__|__] [08|10|11|__] [12|13|14|__] [16|17|18|__]

Як бачите, після цих операцій із вставкою у нас наразі виділено 5 сторінок даних, які можуть вмістити 20 рядків, але у нас є лише 14 рядків ("витрачаючи" 30% місця).

Поновлення з параметрами за замовчуванням (див. Нижче про "коефіцієнт заповнення") призведе до:

[00|02|03|04] [06|08|10|11] [12|13|14|16] [17|18|__|__]

збереження однієї сторінки на цьому простому прикладі. Неважко зрозуміти, як делети можуть мати подібний ефект, як і вставки поза індексом.

Пом'якшення наслідків

Якщо ви очікуєте, що дані прийдуть у досить випадковому порядку щодо порядку індексів, ви можете використовувати FILLFACTORпараметр під час створення або відновлення індексу, щоб сказати SQL Server штучно залишити прогалини, щоб пізніше заповнити - скорочення розбиття сторінки в перспективі, але займаючи більше місця спочатку Звичайно, неправильне значення може спричинити набагато гірше, ніж покращити ситуацію, тому поводьтеся обережно.

Розбиття сторінок, особливо на кластерному індексі, може мати наслідки для продуктивності вставок / оновлень, тому FILLFACTORіноді виправляється з цієї причини замість проблеми використання місця в базах даних, які бачать велику активність запису (але для більшості програм, де читання переважає над записом на кілька порядків, як правило, краще залишити коефіцієнт заповнення на 100%, за винятком конкретних випадків, наприклад, коли у вас є індекси над стовпцями з фактично випадковим вмістом).

Я припускаю, що інші БД з великими іменами мають подібний варіант, якщо вам потрібен і такий рівень контролю в них.

Оновлення

Щодо ALTER INDEXвисловлювання, доданого до запитання після того, як я почав вводити вище: я припускаю, що параметри такі ж, як і коли спочатку був побудований (або останній перебудований), але якщо ні, то варіант стиснення може бути дуже значним, якби це було додано це час навколо. Також у цьому викладі заповнювач встановлюється на 85%, а не на 100%, тому кожна сторінка сторінки буде порожньою ~ 15% одразу після відновлення.


2
+1 Якщо коефіцієнт заповнення сторінки менше 100%, наприклад, якщо коефіцієнт заповнення сторінки становив 50%, щойно відреставрований кластерний індекс ( таблиця ) був би вдвічі більшим, ніж якби він був відновлений зі 100% коефіцієнтом заповнення.
Макс Вернон

6

Після відновлення індексу він буквально розміщує всі дані на нових сторінках. Я підозрюю, що ви видалили багато даних до відновлення, наприклад, вилучили стовпчик, оновили стовпчик змінної ширини, щоб було менше даних, змінили розмір стовпця фіксованої ширини або видалили багато рядків. Жодна з цих операцій може залишити багато порожнього місця на сторінках, які не відновляться до відновлення. Стовпець "Дані" в sp_spaceusedне вимірює фактичні дані, а кількість 8K сторінок, які використовуються для зберігання даних. Ці сторінки тепер переповнені через перебудову, тому однакова кількість даних вміщується на меншій кількості сторінок.


5

sp_spaceusedПроцедура не розглядає загальний culmulative розміру рядків в базі даних. Він повідомляє про розмір місця, виділеного для зберігання цих даних, у сукупному розмірі розширень, виділених для даних.

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

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

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