Я тестирую разные архитектуры для больших таблиц, и я видел одно предложение - использовать секционированное представление, при котором большая таблица разбивается на серию меньших «секционированных» таблиц.
Тестируя этот подход, я обнаружил что-то, что не имеет большого смысла для меня. Когда я фильтрую «столбец разделения» в представлении фактов, оптимизатор ищет только соответствующие таблицы. Кроме того, если я фильтрую этот столбец таблицы измерений, оптимизатор удаляет ненужные таблицы.
Однако, если я отфильтрую какой-либо другой аспект измерения, оптимизатор будет искать PK / CI каждой базовой таблицы.
Вот вопросы, о которых идет речь:
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where o.ObservationDateKey >= 20000101
and o.ObservationDateKey <= 20051231
group by od.[Year];
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where od.DateKey >= 20000101
and od.DateKey <= 20051231
group by od.[Year];
select
od.[Year],
AvgValue = avg(ObservationValue)
from dbo.v_Observation o
join dbo.ObservationDates od
on o.ObservationDateKey = od.DateKey
where od.[Year] >= 2000 and od.[Year] < 2006
group by od.[Year];
Вот ссылка на сессию SQL Sentry Plan Explorer.
Я работаю над секционированием таблицы большего размера, чтобы посмотреть, получу ли я удаление раздела, чтобы ответить таким же образом.
Я получаю исключение раздела для (простого) запроса, который фильтрует по аспекту измерения.
А пока вот копия базы данных только для статистики:
https://gist.github.com/swasheck/9a22bf8a580995d3b2aa
«Старый» оценщик количества элементов получает менее дорогой план, но это из-за более низких оценок количества элементов для каждого (ненужного) индекса поиска.
Я хотел бы знать, есть ли способ заставить оптимизатор использовать ключевой столбец при фильтрации по другому аспекту измерения, чтобы он мог исключить поиски в нерелевантных таблицах.
Версия SQL Server:
Microsoft SQL Server 2014 - 12.0.2000.8 (X64)
Feb 20 2014 20:04:26
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
источник
CREATE STATISTICS [_WA_Sys_00000008_2FCF1A8A] ON [dbo].[Observation_2010]([StationStateCode]) WITH STATS_STREAM = 0x01000000010000000000000000000000D4531EDB00000000D5080000000000009508000000000000AF030000AF000000020000000000000008D000340000000007000000E65DE0007DA5000076F9780000000000867704000000000000000000ABAAAA3C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ObservationDates
таблице. У меня не такой же план, как у Пола, даже с 4199, и я думаю, что именно поэтому.ObservationDates
. Я закончил работатьUPDATE STATISTICS ObservationDates WITH ROWCOUNT = 10000
вручную, чтобы получить план, который продемонстрировал Пол.ObservationDates
так что я не уверен, что с этим происходит. Кроме того, я также не могу получить план Пола. Я попробую обновление, чтобы увидеть.Ответы:
Включить флаг трассировки 4199.
Я также должен был выпустить:
чтобы получить планы, показанные ниже. Статистика по этой таблице отсутствовала при загрузке. Число 73 049 было получено из информации о количестве элементов таблицы в приложении Plan Explorer. Я использовал SQL Server 2014 с пакетом обновления 1 (SP1) CU4 (сборка 12.0.4436) с двумя логическими процессорами, максимальный объем памяти был установлен на 2048 МБ, и никаких флагов трассировки, кроме 4199.
Затем вы должны получить план выполнения с функцией динамического удаления разделов:
Фрагмент плана:
Это может выглядеть хуже, но все фильтры - это фильтры запуска . Пример предиката:
На каждой итерации цикла запускается предикат запуска, и только если он возвращает значение true, выполняется поиск кластеризованного индекса ниже его. Следовательно, устранение динамических разделов.
Это, возможно , не совсем так эффективно , как статическая ликвидация, особенно если план параллельно.
Возможно, вам придется попробовать подсказки, например
MAXDOP 1
,FAST 1
илиFORCESEEK
в представлении, чтобы получить тот же план. Выбор стоимости оптимизатора с многораздельными представлениями (такими как многораздельные таблицы) может быть сложным.Дело в том, что вам нужен план, который включает в себя фильтры запуска, чтобы получить динамическое удаление разделов с разделенными представлениями.
Запросы со встроенными
USE PLAN
подсказками: (через gist.github.com):источник
Я всегда наблюдал, что вы должны явно указать значение (или диапазон значений) для столбца раздела в запросе, чтобы получить «исключение таблицы» в разделенном представлении. Это основано на опыте использования многораздельных представлений в производственной среде от SQL Server 2000 до SQL Server 2014.
В SQL Server отсутствует концепция оператора объединения циклов, в котором механизм может динамически направлять поиск непосредственно на соответствующую таблицу на внутренней стороне цикла на основе значения строки на внешней стороне цикла. Однако, как объясняет ответ Павла , существует возможность плана с начальными фильтрами, чтобы динамически пропускать нерелевантные таблицы на внутренней стороне цикла в постоянное время (в отличие от логарифмического, фактически выполняя поиск).
Обратите внимание, что для многораздельных таблиц этот тип поиска (для конкретного раздела) поддерживается.
Если вы исправили использование секционированных представлений, другой вариант - разделить ваш запрос на несколько запросов, таких как:
Это дает следующий план. Теперь есть дополнительный запрос, который попадает в таблицу измерений, но запрос к таблице фактов (предположительно, намного большего размера) оптимизирован.
источник
20000101
и20051231
вместо переменных (или делаете что-то подобное через два отдельных запроса в вашем приложении), тогда да, тот же эффект будет достигнут без использования переменных.