Використання індексованих представлень для агрегатів - занадто добре, щоб бути правдою?


28

У нас є сховище даних з досить великою кількістю записів (10-20 мільйонів рядків) і часто виконуємо запити, які підраховують записи між певними датами, або рахують записи з певними прапорами, наприклад

SELECT
    f.IsFoo,
    COUNT(*) AS WidgetCount
FROM Widgets AS w
JOIN Flags AS f
    ON f.FlagId = w.FlagId
WHERE w.Date >= @startDate
GROUP BY f.IsFoo

Виступ не жахливий, але може бути досить млявим (можливо, 10 секунд у холодному кеші).

Нещодавно я виявив, що можу використовувати GROUP BYв індексованих поданнях, і тому випробував щось подібне до наступного

CREATE VIEW TestView
WITH SCHEMABINDING
AS
    SELECT
        Date,
        FlagId,
        COUNT_BIG(*) AS WidgetCount
    FROM Widgets
    GROUP BY Date, FlagId;
GO

CREATE UNIQUE CLUSTERED INDEX PK_TestView ON TestView
(
    Date,
    FlagId
);

В результаті ефективність мого першого запиту зараз становить <100 мс, а отриманий вигляд та індекс - <100 к (хоча наш ряд рядків великий, діапазон дат та ідентифікаторів прапор означає, що цей вид містить лише 1000-2000 рядків).

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

Мені це здається занадто гарним, щоб бути правдою - чи не так? З чим я повинен бути обережним, коли таким чином використовуються індексовані види?


2
Чи можете ви переписати свої сценарії, щоб вони насправді були дійсними SQL? Ваші SELECTта CREATE VIEWсценарії помиляються, як я вважаю, це ваш CREATE INDEXсценарій.
Марк Сінкінсон

2
@MarkSinkinson Вибачте, виявляється, що намагатися написати дійсний SQL для уявних таблиць важко
Джастін

Для мене частина "занадто добре, щоб бути правдою" з'явилася тоді, коли я хотів більш досконалих поглядів, таких як MAX, self або external приєднується або індексує погляд, який сам посилається на інший погляд - все, що в SQL Server принаймні не є дозволено docs.microsoft.com/en-us/sql/relational-databases/views/… . Тому я завжди закінчуюсь надто амбітним, а потім мені потрібно змінити масштаби речей. Але для більш простих агрегацій вони справді чудові - підтримується навіть SUM.
Simon_Weaver

Відповіді:


29

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

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

На жаль, багато людей думають, що індексація подання є магічною - індекс не зробить усі представлення даних більш ефективними, особливо перегляди, які просто приєднуються до таблиць та / або створюють таку ж кількість рядків, що і джерело (або навіть множать). У цих випадках введення-виведення з виду є однаковим або навіть гіршим, ніж оригінальний запит, не тільки тому, що є однакові чи більше рядків, але часто вони також зберігають і матеріалізують більше стовпців. Таким чином, заздалегідь матеріалізація не приносить жодних вигод, оскільки - навіть із SSD дисками - введення / виведення, мережа та обробка / рендерінг клієнтів все ще залишаються основними вузькими місцями у поверненні великих наборів результатів клієнту. Економія, яку ви отримуєте, уникаючи приєднання під час виконання просто не вимірюється порівняно з усіма іншими ресурсами, які ви все ще використовуєте.

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

Боже, я мав на увазі блог на цю тему.


19

Відповіді Ааронів добре висвітлювали це питання. Дві речі, які слід додати:

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

Я використовував як агрегацію, так і об'єднання поглядів з надзвичайною вигодою.

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

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