Некластеризованные индексы - ключи и неключи

8

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

Вот моя теория из запроса, который я только что оптимизировал, путем проб и ошибок и чтения документации MSDN.

Запрос

DECLARE @pic_id int
SET pic_id = 1

SELECT ROW_NUMBER() OVER (ORDER BY pic_date desc) AS row_num, *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND (hidden = 0 OR pic_id = @pic_id)

Индекс

CREATE NONCLUSTERED INDEX [IX_tbl_pics] ON [dbo].[tbl_pics] 
(
    [map_id] ASC,
    [deleted] ASC,
    [pic_date] DESC
)
INCLUDE ( [hidden], [pic_id] )

Существует также индекс PK на pic_id

Теория

Ключевые столбцы таковы, потому что они используются либо в предложении WHERE (но не используются в ситуации OR), либо в ORDER BY.

Неключевые (INCLUDE) столбцы как таковые, потому что они используются в WHERE, а потому что они используются в сценарии ИЛИ, они не могут (не могут = не улучшить производительность) быть ключевым столбцом.

Эти предположения верны? Если нет, то что мне не хватает?

Спасибо!

Darthtong
источник

Ответы:

8

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

SELECT *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND hidden = 0;

Остальное пух (в том числе OR pic_id = @pic_id). Это будет сканирование таблицы, гарантировано, из - за низкой селективности предикатов , участвующих (я уверен , что deletedи hiddenв 0/1, и map_ipя сомневаюсь , что это имеет какое - либо значительное влияние). Единственный предикат, который может сохранить запрос, - pic_id = @pic_idэто поместить его в условие ИЛИ, которое вы убили, - это шанс. Реально никакой вторичный индекс не может помочь. Скорее всего, добавление ROW_NUMBER будет рекламировать сортировку, но реальный ущерб - это сканирование.

Это безнадежное дело. Придумайте реалистичные требования.

Ремус Русану
источник
6

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

Что касается того, о чем вы говорите с OR, то это фактически вторая часть WHERE, но вы просто полагаетесь на избирательность первого, выполняющего большую часть работы (полагаясь на INCLUDE, чтобы избежать стол).

Но, имея * там, вы все равно можете пойти к столу.

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

Кейд Ру
источник