SQL-запрос не использует доступный индекс (SQL Server 2008) - PullRequest
2 голосов
/ 14 мая 2009

У меня есть следующая таблица в SQL Server 2008:

Session
(
sessionid varchar(10)
startdate dateteime
enddate dateteime
--rest of the fields go here
)

У меня созданы следующие два некластеризованных индекса:

Inddex1: SessionID,startdate,enddate
Inddex2: startdate,enddate

У меня есть следующий запрос

select *
from session
where startdate>=@date1 and enddate <=@date2

при выполнении этого запроса оба эти идекса не используются. План запроса показывает только сканирование таблицы.

Теперь я попытался удалить index1 и выполнил тот же SP По-прежнему index2 не используется.

Есть какие-нибудь подсказки о том, как заставить SP использовать index2? (Не используйте принудительное использование индекса, пожалуйста.)

Ответы [ 5 ]

3 голосов
/ 14 мая 2009

Возможно, у вас есть кластеризованный индекс для столбца SessionID? В этом случае ваши индексы в основном идентичны, так как любой некластеризованный индекс будет неявно включать кластеризованный ключ.

Сколько строк в таблице и какова мощность / уникальность значений? Если таблица достаточно мала, сканирование таблицы может быть более эффективным, чем поиск по индексу + поиск по закладкам для извлечения оставшихся столбцов.

1 голос
/ 14 мая 2009

Во-первых, неплохо иметь первичный ключ, который вы используете в качестве уникального кластерного индекса.

Я не уверен, что понял смысл этих двух составных индексов. Разве вам не лучше с индивидуальным индексом по датам?

0 голосов
/ 14 мая 2009

Любой индекс с "startdate" в качестве первого столбца может помочь с поиском startdate> = @ date1. Любой индекс с «конечной датой» в качестве первого столбца может помочь с поиском «конечной даты <= @ date2». Но нет никакого индекса, который мог бы помочь с обоими. </p>

И если предположить, что с той же начальной датой почти нет конечных дат, индекс on (startdate, enddate) не более полезен, чем индекс on (startdate).

Таким образом, сканирование таблиц выглядит как надежный выбор для Sql Server.

Даже если вы ищете startdate> = @ date1, все равно имеет смысл выполнить сканирование таблицы. Сканирование индекса дало бы вам много ссылок на таблицу, которую вам нужно было бы разрешить, но это не стоит большого количества данных.

Один запрос, который должен использовать индекс:

select * from session where startdate = @date1

В любом случае, если вы считаете, что знаете лучше, чем оптимизатор, вы можете принудительно использовать индекс, например:

select *
from session with (index indexname)
where startdate>=@date1 and enddate <=@date2
0 голосов
/ 14 мая 2009

Вы говорите, что обработчик запросов не использует один из ваших индексов, но вы не говорите нам, что он делает . Я предполагаю, что сканирование таблицы ...?

У вас нет индекса покрытия для вашего запроса. Поскольку вы выполняете «select *», обработчик запросов знает, что в лучшем случае он может получить только «закладку» из вашего индекса (любой из этих индексов), а затем ему придется сопоставить эту закладку с фактические страницы данных в вашей таблице.

Обладая этими знаниями, обработчик запросов будет проверять объем данных в вашей таблице. Если объем данных там небольшой (для некоторого определения маленький), он может решить, что сканирование таблицы более эффективно, чем поиск по индексу с последующим поиском по закладкам.

Попробуйте изменить запрос и / или индекс, чтобы выбрать только те поля, которые полностью покрыты индексом. Тогда я ожидаю, что вы увидите использование индекса. Но это не обязательно правильно - создание огромного индекса для редко используемого запроса может быть неправильным.

0 голосов
/ 14 мая 2009

Составной индекс не будет использоваться, поскольку он не может использоваться для оптимизации этого запроса. Вы должны создать отдельный индекс для каждого столбца.

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