sql различия между полями индекса и индексом с включенными полями

Я улучшал производительность некоторых сценариев запросов sql. Например:

SELECT * 
FROM Book b, Library l, [Order] o 
WHERE o.bookid = b.bookID 
AND o.mode = 'A' 
AND o.library_ID = l.library_ID 
AND l.library_ID > 19 
AND b.publisher_id  > 1000 
AND b.print_id > 800 
AND NOT EXISTS (
  SELECT * 
  FROM ExtBOOK 
  WHERE b.bookid = extbookid 
  AND library_ID = l.library_ID
) 
AND o.activated = 'Y' 
AND b.eisbn13 LIKE '978%' 
AND len(o.ext_user_id) > 3 
AND b.bookid > 200000 
AND b.bookid in (
  SELECT bookid 
  FROM category 
  WHERE categoryid  > 2
) 
ORDER BY o.orderid DESC

Когда я ищу этот sql-скрипт в SQL Management Studio с помощью «Включить фактический план выполнения», результат просит меня добавить ниже индекс

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Order] ([MODE],[ACTIVATED],[LIBRARY_ID],[BOOKID])
INCLUDE ([OrderID],[EXT_USER_ID],[APPROVAL_DATE])

Однако, если я удалю какие-то условия, как показано ниже:

SELECT * FROM Book b, Library l, [Order] o 
WHERE o.bookid = b.bookID 
AND o.mode = 'A' 
AND o.library_ID = l.library_ID 
AND l.library_ID > 19 
ORDER BY o.orderid DESC

У меня есть еще одна рекомендация, как показано ниже:

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[ORDER] ([MODE])
INCLUDE ([LIBRARY_ID],[BOOKID])

Поскольку условия являются переменными, какой индекс мне следует создать? Я понимаю, что делают индексы, но не понимаю преимуществ между индексируемым полем и включенным полем. Почему в первом рекомендованном индексе BOOKID и LIBRARY_ID находятся в полях индекса, а во втором рекомендуемом индексе BOOKID и LIBRARY_ID находятся во включенных полях? В чем различия, и что мне следует использовать, чтобы охватить все возможные условия?

Кроме того, из своего теста я добавил каждый из них, чтобы проверить производительность, но не вижу никакой разницы. Я ценю любую помощь.


person danmiao    schedule 20.06.2012    source источник
comment
Столбцы индекса являются частью фактической структуры навигации индекса, например вы можете использовать их в предложении WHERE. Включенные столбцы присутствуют только на конечном уровне индекса - вы не можете использовать их для выбора строк - и они там, поэтому ваш запрос может быть удовлетворен (все столбцы, запрошенные запросом) только из index, чтобы вам не приходилось выполнять дорогостоящий поиск ключей в фактических данных таблицы, чтобы получить один или два дополнительных столбца, которые вам нужны.   -  person marc_s    schedule 20.06.2012
comment
@danmiao: на какую таблицу ссылается псевдоним m (m.libary_ID = l.library_ID)? Это опечатка или в запросе есть другая таблица?   -  person 8kb    schedule 20.06.2012
comment
Привет, 8кб, извините, это моя опечатка, это «о», я обновился, спасибо   -  person danmiao    schedule 20.06.2012
comment
Привет, marc_s, большое спасибо, я понял ваши средства, аналогичный вопрос, я могу использовать включенные столбцы для order by, или мне нужно использовать столбцы индекса для order by, или order by не нуждается в индексе.   -  person danmiao    schedule 20.06.2012
comment
Если вы хотите использовать столбец в предложении WHERE или ORDER BY, он должен быть частью фактического индекса и храниться в структуре навигации индекса. Если у вас есть столбец в качестве включенного столбца, индекс нельзя использовать для ORDER BY   -  person marc_s    schedule 20.06.2012


Ответы (1)


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

Это также зависит от того, насколько предсказуемы ваши запросы - предсказуемы ли они, и в каком случае инкапсулируйте их в хранимые процедуры или параметризованные запросы, или они полностью спонтанные?

Полагаю, у вас уже есть индексы для Order.BookID и Order.Library_ID?

Кроме того, я бы перефразировал запросы, чтобы использовать синтаксис внутреннего соединения, то есть:

SELECT * 
FROM [Order] o 
     INNER JOIN Library l
          ON o.library_ID = l.library_ID  
     INNER JOIN Book b  
          ON o.bookid = b.bookID 
WHERE 
     o.mode = 'A'  
AND 
     l.library_ID > 19 
person podiluska    schedule 20.06.2012
comment
Привет, podiluska, действительно, у меня есть индексы для Order.BookID и Order.Library_ID, однако я видел, что вы просто изменили неявное внутреннее соединение на явное внутреннее соединение, есть ли между ними разница в производительности запроса. - person danmiao; 21.06.2012
comment
Не обычно, но я думаю, что это проясняет намерение, что может улучшить ремонтопригодность - person podiluska; 21.06.2012