Почему оптимизатор запросов полностью игнорирует индексированные индексы просмотра?
SQL Fiddle: http://sqlfiddle.com/#!6/d4496/1 (данные предварительно сгенерированы для ваших экспериментов)
Существует очевидная таблица:
CREATE TABLE Entity ( ID int, Classificator1ID int, Classificator2ID int, Classificator3ID int, Classificator4ID int, Classificator5ID int );
и вид:
- Индексный индекс Sql-сервера
- SQL Server ISDATE в индексированном виде
- Можно ли создать индексированный вид с SQL Server 2008, который выбирает из другого индексированного представления?
- Почему запрос был бы быстрее в SQL Server 2005 только потому, что он в представлении?
- Строка даты жесткого кодирования намного быстрее, чем DateTime в SELECT?
CREATE VIEW dbo.EntityView (ID, Code1, Code2, Code3, Code4, Code5) WITH SCHEMABINDING
где сущности полей Classificator1ID..Classificator5ID разрешены для значений классификаторов Code1..Code5
и есть много указателей на эту точку зрения:
CREATE UNIQUE CLUSTERED INDEX [IXUC_EntityView$ID] ON EntityView ([ID]); CREATE UNIQUE NONCLUSTERED INDEX [IXU_EntityView$ID$include$ALL] ON EntityView ([ID]) INCLUDE (Code1, Code2, Code3, Code4, Code5); CREATE UNIQUE NONCLUSTERED INDEX [IXU_EntityView$ALL] ON EntityView ([ID],Code1, Code2, Code3, Code4, Code5); CREATE UNIQUE NONCLUSTERED INDEX [IXU_EntityView$ID$Code1] ON EntityView ([ID],Code1); CREATE UNIQUE NONCLUSTERED INDEX [IXU_EntityView$ID$include$Code1] ON EntityView ([ID])INCLUDE (Code1); CREATE NONCLUSTERED INDEX [IX_EntityView$Code1] ON EntityView (Code1); CREATE NONCLUSTERED INDEX [IX_EntityView$Code1$include$ID] ON EntityView (Code1) INCLUDE (ID);
Но QO никогда их не используют! Попробуй это:
SELECT * FROM EntityView; SELECT ID, Code1 FROM EntityView; SELECT ID, Code1, Code2, Code3, Code4, Code5 FROM EntityView; SELECT ID, Code1, Code2, Code3, Code4, Code5 FROM EntityView WHERE ID=1; SELECT ID, Code1 FROM EntityView Where Code1 like 'NR%';
Зачем? И особенно Что не так с индексами «включить»? индекс создан, имеет все поля и еще не используется …
ДОБАВЛЕНО: ЭТО ТОЛЬКО ТЕСТ! Пожалуйста, не будьте так злы и не подталкивайте меня к анализу этих проблем.
В моем реальном проекте я не могу объяснить, почему QO игнорирует индексированные представления (очень-очень полезные индексированные представления). Но иногда я вижу, что они используют их в других местах. Я создал этот фрагмент db, чтобы поэкспериментировать с формулами индекса, но может быть, я должен сделать что-то еще: как-то настроить statistcs?
- Как эффективно проверить, содержит ли база данных идентичную запись для ожидающей вставки?
- SQL Server - иногда плохой показатель производительности и недостающий указатель - почему?
- Медленность при индексированном представлении для SQL 2005
- Показатель индекса SQL Server - длинный столбец
- Как я могу прекратить объединение с добавлением строк в моем запросе соответствия?
- Как ускорить массовое обновление кластерного столбца?
- Visual Studio-подобный инструмент рефакторинга для SQL
- Можно ли получить список релевантных слов из полнотекстового индекса, заданного определенной строкой?
Запуск в 2012 году Developer Edition безцелевой запрос стоит примерно в 8 раз больше, чем намеченный запрос
В то время как коэффициент 8 может показаться много вашим примером, данные довольно малы, а затраты на выбор непосредственно из базовых таблиц составляют 0.0267122
против 0.003293
для сметной стоимости с точки зрения.
Пол Уайт объясняет в своем ответе, что автоматическое индексированное сопоставление взглядов даже не будет рассмотрено, если сначала найти достаточно низкий план.
Искусственно увеличивая затраты на все задействованные таблицы
UPDATE STATISTICS Classificator1 WITH ROWCOUNT = 60000000, PAGECOUNT = 10000000 UPDATE STATISTICS Classificator2 WITH ROWCOUNT = 60000000, PAGECOUNT = 10000000 UPDATE STATISTICS Classificator3 WITH ROWCOUNT = 60000000, PAGECOUNT = 10000000 UPDATE STATISTICS Classificator4 WITH ROWCOUNT = 60000000, PAGECOUNT = 10000000 UPDATE STATISTICS Classificator5 WITH ROWCOUNT = 60000000, PAGECOUNT = 10000000 UPDATE STATISTICS Entity WITH ROWCOUNT = 60000000, PAGECOUNT = 10000000
Увеличивает стоимость плана базовой таблицы до 29122.6
Теперь вы должны увидеть совпадение вида (в выпусках Enterprise / Developer / Evaluation), если вы явно не намекаете иначе.
SELECT * FROM EntityView; SELECT * FROM EntityView OPTION (EXPAND VIEWS)
tl; dr ответ: если вы не укажете NOEXPAND, оптимизатор запросов не имеет представления, что вы отправляете простой выбор из представления. Это должно было бы соответствовать расширению вашего запроса (что все, что он видит) с некоторым индексом просмотра. Наверное, не стоит беспокоиться, когда это пятиступенчатое соединение с кучей отливок.
Сравнение индексов с запросом является сложной проблемой, и я считаю, что ваше представление слишком сложно, чтобы механизм запросов соответствовал индексу. Рассмотрим этот один из ваших запросов:
SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';
Для вас очевидно, что это может использовать индекс просмотра, но это не тот запрос, который видит механизм запросов. Представления автоматически расширяются, если вы не укажете NOEXPAND, так что это то, что касается механизма запроса:
SELECT ID, Code1 FROM ( SELECT e.ID, 'NR'+CAST(c1.CODE as nvarchar(11)) as Code1, 'NR'+CAST(c2.CODE as nvarchar(11)) as Code2, 'NR'+CAST(c3.CODE as nvarchar(11)) as Code3, 'NR'+CAST(c4.CODE as nvarchar(11)) as Code4, 'NR'+CAST(c5.CODE as nvarchar(11)) as Code5 FROM dbo.Entity e inner join dbo.Classificator1 c1 on e.ID = c1.ID inner join dbo.Classificator2 c2 on e.ID = c2.ID inner join dbo.Classificator3 c3 on e.ID = c3.ID inner join dbo.Classificator4 c4 on e.ID = c4.ID inner join dbo.Classificator5 c5 on e.ID = c5.ID; ) AS V;
Механизм запросов видит этот сложный запрос и содержит информацию (но, вероятно, не SQL-определения), которые описывают индексы представления, которые были определены. Учитывая, что этот запрос и индексы представлений имеют множественные объединения и отливки, сопоставление является трудным заданием.
Имейте в виду, что вы знаете, что соединения и совпадения идентичны в этом запросе и индексы представления, но процессор запросов этого не знает. Он обрабатывает этот запрос так же, как если бы он присоединился к пяти экземплярам Classificator3, или если один из столбцов был «NQ» + CAST (c2.CODE как varchar (12)). Средство просмотра индекса (при условии, что оно сделало любую попытку сопоставить этот сложный запрос) должно было бы сопоставить каждую деталь этого запроса с деталями индексов представления в соответствующих таблицах.
У механизма запроса есть цель №1, чтобы выяснить способ эффективного выполнения запроса. Вероятно, он не предназначен для много времени, пытаясь сопоставить каждую деталь пятистороннего соединения и CASTs с индексом представления.
Если я должен был догадаться, я подозреваю, что совпадение индексов представления видит, что столбцы результатов запроса не являются даже столбцами любой базовой таблицы (из-за CAST) и просто не пытаются что-либо попробовать. Добавлено : я ошибаюсь. Я просто попробовал предложение Мартина по обновлению статистики, чтобы сделать запрос дорогим, и индекс просмотра был сопоставлен для некоторых из этих запросов без NOEXPAND. Совместитель вида умнее, чем я думал! Таким образом, проблема заключается в том, что совпадение вида, вероятно, пытается сложнее сопоставить сложный запрос, если его стоимость очень высока.
Используйте подсказку NOEXPAND вместо того, чтобы ожидать, что механизм запросов сможет определить, что здесь соответствует. NOEXPAND – это абсолютно ваш друг, потому что тогда механизм запросов добирается до
SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';
и тогда сразу же видно, что индексный признак имеет полезный индекс.
(Примечание: ваш код SQL Fiddle содержит все 5 ссылок на внешние ключи в одну и ту же таблицу, что, вероятно, не то, что вы хотите.)
Используйте подсказку WITH (NOExpand), если вы находитесь на сервере SQL Server Enterprise
Ваш запрос будет SELECT * FROM EntityView with (noexpand)