Статистика. Возможны ли многоколонные гистограммы?

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

JGA
источник
Почему бы не построить некоторые индексы на 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 (с включенным новым оценщиком мощности) изменено с Независимости на Экспоненциальный откат (подробнее здесь и здесь ). В конечном счете, это просто другое предположение. Во многих случаях будет лучше, а в других - хуже.

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

Пол Уайт 9
источник