Які дійсні сценарії використання для таблиць HEAP?


31

Зараз я здійснюю імпорт даних у застарілу систему і виявив, що ця система не використовує єдиного кластерного індексу. Швидкий пошук Google познайомив мене з концепцією таблиць HEAP, і тепер мені цікаво, у яких сценаріях використання таблиця HEAP слід віддавати перевагу кластерній таблиці?

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


1
Ви говорите про SQL Server?
a_horse_with_no_name

@a_horse_with_no_name так, я забув згадати цю
sry

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


Відповіді:


22

Єдине дійсне використання призначене для

  • таблиці постановок, що використовуються в процесах імпорту / експорту / ETL.
  • тимчасове та короткочасне резервне копіювання таблиць із використанням SELECT * INTO..

Столи для постановки, як правило, досить плоскі та усічені перед / після використання.

Зауважте, що кластерний індекс, як правило, мало малий порівняно з розміром даних: дані є найнижчим рівнем структури індексу.

Купи столів також мають проблеми. Принаймні такі:

Також див


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

Добре питання до речі.
Зане

1
Невелике налаштування - якщо ви зробите SELECT INTO, щоб створити швидке резервне копіювання невеликої таблиці, перш ніж вносити зміни, за замовчуванням створюється купа. Я б сказав, що це правильне використання, але це лише збирання азоту. Я хотів би позбутися цієї купи, як тільки знаю, що моя робота зроблена.
Брент Озар

@BrentOzar: Погодьтеся, я весь час це роблю сам. Дух моєї відповіді - "довгострокові та стійкі таблиці", але я
оновлю

9

Основні міркування

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

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

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

  • Індекси на купи опорних RID, які є 64 бітами. Як уже згадувалося, некластеризовані індекси в кластеризованій таблиці посилаються на кластеризаційний ключ, який може бути меншим (32-бітовим INT), таким же (64-бітовим BIGINT) або більшим (48-бітний DATETIME2()плюс 32-розрядний INT, або 128-бітний GUID). Очевидно, що більш широке посилання дає великі та дорожчі індекси.

Вимоги до місця

За допомогою цих двох таблиць:

CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)

CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)

... для кожного з 8,7 М записів необхідний простір становив 150 МБ для даних для обох; 120 МБ для індексів кластерної таблиці, 310 МБ для індексів некластеризованої таблиці. Це відображає, що кластерний індекс вужчий, ніж RID, і що індекс кластеризації є здебільшого "халявою". Без унікальних індексів ID2необхідний простір індексів падає до 155 МБ для некластеризованої таблиці (наполовину, як можна було б очікувати), але всього 150 Кб для кластеризованої ПК - майже нічого.

Так некластеризований індекс 32-бітного поля в кластеризованій таблиці з 32-бітовим індексом (всього 64 біта, номінально) займав 120 МБ, тоді як індекс 32-бітного поля в купі з 64-бітним RID (всього 96 біт, номінально) займає 155 Мб, трохи менше 50% збільшення, можна було б наївно очікувати переходу від 64-бітних до 96-бітних клавіш, але, звичайно, є накладні витрати, що зменшує ефективну різницю в розмірах.

Складання двох таблиць та створення їх індексів займало однакову кількість часу для кожної таблиці. Проводячи прості тести, що включають сканування або пошук, я не виявив різниці між показниками продуктивності між таблицями, що відповідає білій книзі Microsoft, яка gbn корисно пов'язана. Згаданий папір показує суттєву різницю для високо одночасного доступу; Я не впевнений, чому це трапляється, сподіваємось, нам може сказати хтось із більшим досвідом, ніж я, з великими обсягами OLTP-систем.

Додавання ~ 40 байт даних випадкових змінної довжини суттєво не змінило цю еквівалентність. Заміна INTs на широкі UUID також не відбулася (кожна таблиця була уповільнена приблизно в однаковій мірі). Ваш пробіг може відрізнятися, але в більшості випадків, чи є індекс, важливіше, ніж який вид.

Шматочки та шматочки

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

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

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

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

TL; DR

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

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


5

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

Наш склад завантажує ~ 1,5 мільярда рядків на день і має підтримувати запитання та обробку, які одночасно працюють, а також читають. Реляційний магазин підтримує базу даних OLAP, і тому зчитування, як правило, є головним чином скануванням таблиці. Згенеровані звіти та канали нижче, як правило, недостатньо вибіркові, тому будь-який індекс був би корисним. Система підтримує розсувне вікно даних, і тому після завантаження таблиці ми рідко пишемо в неї знову і, враховуючи досить погану реалізацію розділів таблиці, що вимагає блокування Sch-M для розбиття розділів, комутаторів та злиття порівняно із замками Sch-S для читання тощо , система повинна була використовувати багато таблиць, хоча у нас є і деякі розділені таблиці. Використання багатьох таблиць сприяє легкості сегментації циклів даних та очищення, а також зменшує суперечки.

Таким чином, додані накладні таблиці індексованої таблиці (кластеризована таблиця) у довільних стовпцях (іх), порівняно з можливістю виконувати bcp у купу, обробляти розділи OLAP, виконувати деякі запити сканування таблиці, а потім через 3 дні скинути це означає, що це просто не варто. Зауважте, що в нашому випадку дані повертаються з великого кластеру сітки, тому немає впорядкування даних, тому вставлення в таблицю з кластерним індексом може ввести інші проблеми, такі як "гарячі точки" та розбиття сторінок тощо.

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

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

[Редагувати] Я, мабуть, повинен уточнити, що лише наші нерозділені таблиці фактів - це купи. Усі розподілені таблиці та таблиці розмірів мають кластерні індекси для підтримки ефективного пошуку тощо. [Edit2] Виправлено 2,5 млрд. До 1,5 млрд. Тет, ці два числа стоять поруч. Що відбувається під час набору відповідей по телефону, я думаю ...

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