Я имею в виду ситуацию, когда у меня есть два столбца с высокой плотностью, но эти столбцы не являются независимыми.
Определение
Вот определение таблицы, которую я создал для целей тестирования.
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
Как и ожидалось, оптимизатор запросов угадывает точное количество строк.
Шаг 2: Фильтрация по col2
SELECT * FROM StatsTest WHERE col2=1
Снова у нас есть прекрасная оценка.
Шаг 3: Фильтрация по col1 и col2
SELECT * FROM StatsTest WHERE col1=1 AND col2=1
Здесь оценка далека от фактического количества строк.
Проблема заключается в том, что простота анализатора запросов предполагает, что col1 и col2 независимы, но это не так.
Шаг 4: Фильтрация по col4
SELECT * FROM StatsTest WHERE col4 = 11
Я могу отфильтровать по col4 = 11, чтобы получить те же результаты, что и запрос в шаге 3, потому что col4 является вычисляемым столбцом и в соответствии с тем, как он был определен, col1 = 1, а col2 = 1 эквивалентно col4 = 11. Однако здесь , как и ожидалось, оценка идеальна.
Заключение / Вопрос
¿Является ли это искусственное и не элегантное решение единственным доступным вариантом для достижения точных оценок при работе с фильтрацией по двум или более независимым столбцам? ¿Является ли вычисляемый столбец и фильтр по вычисляемому столбцу крайне необходимыми для получения фактической точности?
Пример в sqlfiddle
Ответы:
Не правда многомерных гистограмм, нет.
SQL Server поддерживает статистику «из нескольких столбцов» , но они собирают информацию только о средней плотности (корреляции) в дополнение к гистограмме в первом именованном столбце. Они полезны только для сравнения равенства.
Информация о средней плотности не фиксирует никаких деталей, поэтому вы получите одинаковую избирательность для любой пары значений в объекте статистики с двумя столбцами. В некоторых случаях многостолбцовая статистика может быть достаточно хорошей и лучше, чем ничего. Многостолбцовая статистика автоматически строится на многостолбцовых индексах.
В зависимости от версии SQL Server вы также можете использовать отфильтрованные индексы и отфильтрованную статистику :
Или вы можете создать индексированное представление (которое может поддерживать собственные индексы и статистику). Индексированные представления - это механизм
DATE_CORRELATION_OPTIMIZATION
настройки базы данных , мало используемая функция для корреляции между таблицами, но которая относится к духу вопроса.Это не единственный метод. В дополнение к уже упомянутым вещам вы также можете указать точное текстовое определение вычисляемого столбца, и оптимизатор обычно будет сопоставлять его со статистикой по вычисляемому столбцу.
Существуют также флаги трассировки, которые изменяют допущения, сделанные в отношении многоколоночных корреляций. Кроме того, предположение о корреляции по умолчанию в SQL Server 2014 (с включенным новым оценщиком мощности) изменено с Независимости на Экспоненциальный откат (подробнее здесь и здесь ). В конечном счете, это просто другое предположение. Во многих случаях будет лучше, а в других - хуже.
Точная точность оценки мощности не всегда необходима для получения хорошего плана выполнения. Всегда существует компромисс между созданием плана, который можно использовать повторно для различных значений параметров, и планом, который является оптимальным для конкретного выполнения, но не используется повторно.
источник