2009-05-14 4 views
2

я следующую таблицу в SQL Server 2008:SQL запрос не использует доступный индекс (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>[email protected] and enddate <[email protected] 

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

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

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

ответ

3

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

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

+0

+ 1 - маленькие таблицы давно меня бросили, потому что они отказались использовать индексы во многих обстоятельствах (по уважительной причине, я думаю) –

0

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

+1

Неправда. Индекс может (акцент на май) использоваться всякий раз, когда в первом столбце индекса есть предикат. Не должно быть равенства. –

+0

Вы правы. ответ отредактирован. – hopethisworks

1

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

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

0

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

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

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

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

0

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

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

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

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

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

select * from session where startdate = @date1 

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

select * 
from session with (index indexname) 
where startdate>[email protected] and enddate <[email protected] 
+1

Неправда. И индекс вроде (startdate, enddate) отлично подходит для запроса с предикатом, который фильтрует сначала startdate и enddate second. Индекс может использоваться. Если есть много столбцов, фильтрация по этому индексу сама по себе и поиск по закладкам для результатов будет намного дешевле IO-мудрый, чем полный просмотр таблицы. –

+0

Это поможет с помощью «stardate = @a и enddate <@b», и это предотвратит поиск таблицы в «select enddate where startdate> @x». Так что есть редкие исключения. – Andomar

+0

Это также поможет в его точном запросе. Имея индекс как (startdate, enddate) _will_ help в запросе с предикатом типа WHERE startdate> = @startdate AND enddate <= @enddate Поскольку индекс - это в основном только отсортированные данные, это гораздо более быстрый способ фильтрации вниз данные. Используя первый предикат и индекс, мы находим все данные, которые выполняют первый предикат. Учитывая индекс, найденные данные теперь сортируются в соответствии со вторым предикатом, и мы можем таким образом отфильтровать его снова. –

Смежные вопросы