Почему конкретный индекс не используется в запросе? - PullRequest
6 голосов
/ 07 июля 2011

У меня есть таблица с именем Workflow. В нем 37 миллионов строк. В столбце идентификатора (int) есть первичный ключ плюс дополнительный столбец. Столбец ID является первым столбцом в индексе.

Если я выполняю следующий запрос, PK не используется (если я не использую подсказку индекса)

Select Distinct(SubID) From Workflow Where ID >= @LastSeenWorkflowID

Если вместо этого выполнить этот запрос, используется PK

Select Distinct(SubID) From Workflow Where ID >= 786400000

Я подозреваю, что проблема заключается в использовании значения параметра в запросе (что я должен сделать). Я действительно не хочу использовать индексную подсказку. Есть ли обходной путь для этого?

Ответы [ 3 ]

3 голосов
/ 08 июля 2011

Пожалуйста, опубликуйте план (ы) выполнения, а также точное определение таблицы, включая все индексы.

Когда вы используете переменную, оптимизатор не знает, какую селективность будет иметь запрос, @LastSeenWorkflowIDможет отфильтровывать все, кроме самых последних нескольких строк в Workflow, или может включать их все.Сгенерированный план должен работать в обеих ситуациях.Существует порог, при котором поиск диапазона по кластеризованному индексу становится более дорогим, чем полное сканирование некластеризованного индекса, просто потому, что кластеризованный индекс намного шире (он включает каждый столбец в конечных уровнях) и, следовательно, имеетнамного больше страниц для повторения.Сгенерированный план, который учитывает неизвестное значение для @LastSeenWorkflowID, вероятно, пересекает этот порог при оценке стоимости поиска по кластеризованному индексу и поэтому выбирает сканирование по некластерному индексу.узкий индекс, предназначенный специально для этого запроса:

CREATE INDEX WorkflowSubId ON Workflow(ID, SubId);

или:

CREATE INDEX WorkflowSubId ON Workflow(ID) INCLUDE (SubId);

Такой индекс слишком хорош для передачи для вашего запроса, независимо от значения@ LastSeenWorkflowID.

2 голосов
/ 08 июля 2011

Предполагая, что ваш PK является идентификатором ИЛИ всегда больше 0, возможно, вы можете попробовать это:

Select Distinct(SubID) 
From Workflow 
Where ID >= @LastSeenWorkflowID
    And ID > 0

Добавление второго условия может привести к тому, что оптимизатор будет использовать поиск по индексу.

0 голосов
/ 15 июля 2011

Это классический пример локальной переменной, создающей неоптимальный план.

Вы должны использовать OPTION (RECOMPILE), чтобы скомпилировать ваш запрос с фактическим значением параметра ID.

См. Мой блог для получения дополнительной информации: http://www.sqlbadpractices.com/using-local-variables-in-t-sql-queries/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...