Статистика. Чи можливі багатоколінні гістограми?


13

Я думаю про ситуацію, коли у мене є дві колонки з високою щільністю, але ці стовпці не є незалежними.

Визначення

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

CREATE TABLE [dbo].[StatsTest](
    [col1] [int] NOT NULL,  --can take values 1 and 2 only
    [col2] [int] NOT NULL,  --can take integer values from 1 to 4 only
    [col3] [int] NOT NULL,  --integer. it has not relevance just to ensure that each row is different
    [col4]  AS ((10)*[col1]+[col2])  --a computed column ensuring that if two rows have different values in col1 or col2 have different values in col4 
) ON [PRIMARY]

Дані

Дані для експерименту наступні

col1    col2    col3    col4
1       1       1       11
1       2       2       12
1       2       3       12
1       3       4       13
1       3       5       13
1       3       6       13
1       4       7       14
1       4       8       14
1       4       9       14
1       4       10      14
2       1       11      21
2       1       12      21
2       1       13      21
2       1       14      21
2       2       15      22
2       2       16      22
2       2       17      22
2       3       18      23
2       3       19      23
2       4       20      24

Крок 1: Фільтрування по col1

SELECT * FROM StatsTest WHERE col1=1

Як і очікувалося, Оптимізатор запитів здогадується точну кількість рядків. Фактична кількість рядків = 10 та орієнтовна кількість рядків = 10

Крок 2: Фільтрування по col2

SELECT * FROM StatsTest WHERE col2=1

Знову ми маємо ідеальну оцінку.

Фактична кількість рядків = 5 та орієнтовна кількість рядків = 5

Крок 3: Фільтрування по col1 і col2

SELECT * FROM StatsTest WHERE col1=1 AND col2=1

Тут оцінка далеко не близька до фактичної кількості рядків. Фактична кількість рядків = 1 та орієнтовна кількість рядків = 3,53553

Проблема полягає в тому, що неясність аналізатора запитів передбачає, що col1 і col2 є незалежними, але вони не є.

Крок 4: Фільтрування по col4

SELECT * FROM StatsTest WHERE col4 = 11

Я можу відфільтрувати по col4 = 11, щоб отримати ті ж результати, що і запит на кроці 3, тому що col4 - це обчислений стовпець і відповідно до того, як було визначено col1 = 1, а col2 = 1 еквівалентно col4 = 11 Тут, однак, , як очікувалося, оцінка ідеальна.

Фактична кількість рядків = 1 та орієнтовна кількість рядків = 1

Висновок / Питання

Чи є це штучне та неелегантне рішення єдиним доступним варіантом для досягнення точних оцінок при роботі з фільтруванням за двома чи більше незалежними колонками? ¿Чи обчислюваний стовпчик і фільтр обчисленого стовпця суттєво необхідні для отримання фактичної точності?

Приклад у sqlfiddle


Чому б не побудувати деякі індекси на col1 / 2?
LowlyDBA

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

Відповіді:


15

Чи можливі багатоколінні гістограми?

Неправдиві багатовимірні гістограми, ні.

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

SQL Server підтримує статистику "багато стовпців" , але вони фіксують лише інформацію про середню щільність (кореляцію) на додаток до гістограми на першому іменованому стовпчику. Вони корисні лише для порівняння рівності.

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

Залежно від версії SQL Server, ви також можете скористатися відфільтрованими індексами та відфільтрованою статистикою :

-- Filtered statistics example
CREATE STATISTICS stats_StatsTest_col2_col1_eq_1
ON dbo.StatsTest (col2)
WHERE col1 = 1;

CREATE STATISTICS stats_StatsTest_col2_col1_eq_2
ON dbo.StatsTest (col2)
WHERE col1 = 2;

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

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

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

Існують також позначення слідів, які змінюють припущення, зроблені щодо кореляцій у багато стовпців. Також припущення про кореляцію за замовчуванням у SQL Server 2014 (з увімкненим новим оцінкою кардинальності) змінюється з незалежності на експоненційний Backoff (детальніше тут і тут ). Зрештою, це лише інше припущення. У багатьох випадках буде краще, а в інших - гірше.

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

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