2015-07-08 3 views
1

Большинство моих запросов SQL имеют WHERE rec_id <> 'D'; как, например:Почему индекс SQL Server не используется?

select * from Table1 where Field1 = 'ABC' and rec_id <> 'D' 

Я добавил индекс на REC_ID. Но когда я запускаю этот запрос и смотрю план выполнения, новый индекс (REC_ID) не используется. В плане выполнения указывается стоимость 50% индекса nonClustered Field1 и 50% RID Lookup (кучи) в Table1.

Почему индекс REC_ID не используется?

+3

Как определяются ваши индексы? Вы можете добавить 'INCLUDE (Field1)' в определение индекса 'rec_id'. – Siyual

+2

Сколько строк в таблице? Какова мощность, доля строк, возвращаемых к общему количеству строк? – Mihai

+0

Вы также можете попробовать, если использовать индекс даже помогает, включить статистику io и использовать подсказку индекса, чтобы заставить SQL Server использовать его –

ответ

2

SQL Server использует множество факторов, чтобы определить, какие индексы использовать. Он должен был определить, что использование индекса на Field1 будет более эффективным, если использовать индекс на rec_id, а это значит, что field1={value} определяет меньший набор, чем rec_id <> {value} на основе дисперсии данных и т. Д., Поэтому для сравнения с другим условием меньше записей. Обратите внимание, что фактическое значение обычно не имеет значения при определении того, какой индекс использовать.

+0

@ D Стэнли. Я просто снова выполнил запрос с другим значением, чем «ABC», и план выполнения показывает 100% Table1 Table Scan; index Field1 не используется вообще. Я просто решил, стоит ли добавлять индекс REC_ID, но результаты не являются окончательными. Спасибо. – Hidalgo

+0

@Hidalgo Запрос будет использовать только один индекс в таблице, поэтому добавление другого простого индекса не поможет, если индекс в этом поле не приведет к лучшему плану, чем индекс в начальном поле. Добавление индекса _composite_ может помочь, но все зависит от того, что, по мнению SQL Server, является самым оптимальным планом (и это не всегда правильно). –

+0

@ D Стэнли. Я понимаю что ты имеешь ввиду. Я добавил составной индекс, и он используется. Но затем я удалил составной индекс, изменил PK на кластеризованный (он был некластеризованным), и я вижу улучшение. Спасибо. – Hidalgo

3

Для этого запроса:

select * 
from Table1 
where Field1 = 'ABC' and rec_id <> 'D'; 

Лучший показатель table1(Field1, rec_id).

Однако ваш запрос может оказаться не в состоянии использовать индекс. Цель использования индекса для предложения where заключается в уменьшении количества страниц, которые необходимо прочитать. Чтобы понять концепцию некластеризованных индексов на обычных строках, вам понадобятся некоторые основные идеи:

  • Записи хранятся на страницах.
  • Каждая страница имеет 8,192 байт (немного меньше используется для данных) и может хранить некоторое количество записей.
  • Вся страница загружается в память для чтения записи.

Скажем, запись составляет около 80 байт, и на каждой странице записано 100 записей. Если 10% записей имеют Field1 = 'ABC', то на каждой странице будет около десяти. Это означает, что использование индекса не будет (обычно) сохранять любые чтения страниц. Если соответствует 1% записей, то на каждой странице будет по одному. Индекс по-прежнему не помогает.

Если только 0,01% записей совпадают (30 в вашем случае), то нужно прочитать только часть страниц. Это сладкое место для индексов, и там, где они действительно полезны.

Число совпадающих записей называется «избирательность». Если предложение where не очень избирательно, то некластеризованный индекс не будет полезен.

Иногда кластерный индекс может быть полезен в этой ситуации. Однако кластеризованные индексы могут иметь дополнительные накладные расходы для insert и некоторые транзакции update. Таким образом, выбор индекса должен основываться на обрабатываемых запросах и других способах использования таблицы.

+0

@ Gordon Linoff Насколько я понимаю, кластеризованный индекс будет иметь преимущество (не всегда, но часто) при чтении данных и недостатке при написании (иногда). Поскольку я в основном интересуюсь чтением, я изменю свой индекс PK на кластеризованный. По моему опыту пользователь обычно кладет чашку кофе и нажимает на «Получить мои данные» с мыслью «Я хочу это сейчас!» Когда они нажимают «Сохранить», они достигают чашки кофе и не возражают ждать {bg} – Hidalgo

+0

@ Идальго. , , Кластеризованный индекс в поле «Field1, rec_id» может помочь вам. Это должно уменьшить количество загружаемых страниц. Однако, похоже, что запрос может возвращать много, много строк. Если это так, то объем данных может быть существенной частью проблемы производительности. –

+0

@ Гордон. Пример моего первоначального сообщения с Field1 был упрощенным. Когда я преобразовал PK в кластеризованный и выполнил другой запрос, план выполнения показал, что этот кластерный индекс PK использовался. Так вот что мне нужно делать. Спасибо. – Hidalgo

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