Як знизити фрагментацію HEAP у SQL Server?


10

Нещодавно я з'ясував, що одна таблиця купи мала фрагментацію понад 70%. Тому я вирішив зробити

ALTER TABLE dbo.myTable REBUILD

Досить смішно, згодом у мене була 20% фрагментація. З того часу не писали на цьому столі. Тому я вирішив зробити відновлення ще раз.

Після 2-го разу стіл має 50% фрагментацію, ще більше! Я справді не розумію, як це може статися ...


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

2
Я думаю, ми повинні запитати, наскільки великий стіл? У рядках та на сторінках.
Коді Коніор

Відповіді:


17

Що означає фрагментація в купі

Значення фрагментації в Heap, яке ви отримуєте з стовпця avg_fragmentation_in_percent, запитуючи sys.dm_db_index_physical_statsDMV, говорить про це

Логічна фрагментація індексів або фрагментація міри для купи в блоці розподілу IN_ROW_DATA.

Далі той самий BOL говорить про це

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

Таким чином, ви можете бачити, що не вільний простір, присутній на сторінках, виділених на Heap, а різна послідовність сторінок створює фрагментацію.

Це можна продемонструвати невеликим тестом. Створимо таблицю Heap Table і вставимо в неї деякі записи, а потім перевіримо фрагментацію.

create table dbo.HeapTest
(
Id INT not NULL Default (1),
Col1   char(5000) Not null Default ('Heaps Are Cool')
)

SET NOCOUNT ON

Insert into dbo.Heaptest default values
go 50

select index_type_desc,avg_fragmentation_in_percent,fragment_count,
avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats(db_id(),object_id('dbo.HeapTest','U'),0,default,'detailed')

Так створена таблиця Heap з 50 записами. Нижче - як виглядає фрагментація після запиту DMV sys.dm_db_index_physical stats

введіть тут опис зображення

Ви можете бачити, що avg_fragmentation_in_percentзначення стовпця становить 33%. Тепер давайте подивимося, як розташовані сторінки. Це можна зробити за допомогою незадокументованого запиту %%lockres%%. Запит буде

SELECT  %%lockres%%, * FROM dbo.HeapTest;

А нижче - як виглядає вихід. Прикріплюючи лише відповідну його частину. Запит отримав 50 рядків, оскільки ми вставили 50 рядків у нашу таблицю dbo.HeapTest.

введіть тут опис зображення

На ньому написано, що перша сторінка має ідентифікатор, 197наступна сторінка має ідентифікатор, 242наступні сторінки мають постійний ідентифікатор, поки ми не дійдемо до ідентифікатора сторінки, 264оскільки після цього ми отримуємо ідентифікатор сторінки 280. Тож цей стрибок номерів ідентифікаторів сторінки - це те, що насправді викликає фрагментацію.

Тепер, щоб не відновити купу і запустити команду ще раз, щоб побачити фрагментацію та впорядкування сторінок. Ми отримуємо фрагментацію на кшталт

введіть тут опис зображення

Ви можете бачити фрагментацію зараз 14%.

Подивимося виділені номери сторінок

введіть тут опис зображення

У нас є лише один перехідний перехід, всі сторінки виділяються ідентифікатором сторінки серійно. Оскільки лише один фрагмент стрибка значно зменшився.

Я знову відновлюю Кучу, і тепер, коли я перевірив фрагментацію, її повністю не було. І розподіл ідентифікатора сторінки подібний

введіть тут опис зображення

Чому фрагментація зросла

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

На задній частині голови ви також повинні мати на увазі, що слово фрагментація для HEAP не має жодного значення, як би ви визначили фрагментацію для купу невпорядкованих сторінок.

Дуже хвилюється за фрагментацію

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

PS: Будь ласка, не використовуйте недокументовану команду на виробничій системі. Це було лише для демонстрації.


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

Як запустити виділити index_type_desc, avg_fragmentation_in_percent, fragment_count, avg_page_space_used_in_percent, record_count from sys.dm_db_index_physical_stats (db_id (), object_id ('dbo.HeapTest', 'за замовчуванням', 'повернути', результат, лише 0, 'повернутись', результат ',', ',' U ') один стіл? він повертається для всіх індексів для всіх таблиць для мене, навіть якщо я правильно вказати своє ім'я таблиці в 'object_id'
Mickael

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

@Shanky, чому ви не рекомендуєте використовувати незадокументований запит %% lockres %% у виробництві? Не могли б ви це детально пояснити?
Ральф

@ user1624552 Просто тому, що він недокументований, означає, що MS також не оновлює документацію про нього. Які його наслідки, як це працює, ніде не зафіксовано, тому її так і задають. Наприклад, є команда fn_dump_dblog (), яка створює прихований планувальник, і це не добре. Ця команда також не підтримується. Ви можете використовувати його, але ризик лежить на вас.
Шанкі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.