Назад | Перейти на главную страницу

Предлагаемые индексы

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

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Company] ([CreatedById],[TenantId],[CreatedDate])

У меня уже есть следующий индекс:

CREATE NONCLUSTERED INDEX [IX_Company_Tenant] 
ON [dbo].[Company] ([TenantId],[UserId],[CreatedDate])

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

CREATE NONCLUSTERED INDEX [IX_Company_Tenant] 
ON [dbo].[Company] ([TenantId],[UserId],[CreatedDate], [CreatedByID])

Вместо создания индекса, предлагаемого хранилищем запросов?

РЕДАКТИРОВАТЬ

Даже после применения третьего индекса:

CREATE NONCLUSTERED INDEX [IX_Company_Tenant] 
ON [dbo].[Company] ([TenantId],[UserId],[CreatedDate], [CreatedByID])

Я по-прежнему получаю тот же рекомендуемый индекс.

Вы должны создать индекс с точным предложенным порядком столбцов (или с техническим почти эквивалентным порядком столбцов).
Порядок столбцов иногда / часто имеет значение для удобства использования и эффективности индекса для конкретного запроса.

В приведенном выше случае важно иметь CreatedDate позади CreatedByID и TenantId или даже прямо за этими полями (так что нет UserId между ними), чтобы позволить SQL Server напрямую переходить к индексным блокам для CreatedByID и TenantId а затем найти запрошенный CreatedDate начальное значение в последовательных записях заказов для этого столбца и чтение всех ссылок на строки одну за другой, прокручивая индекс, пока не достигнет запрошенного CreatedDate конечное значение (и счетчик приращения для каждой найденной строки).

В отличие от этого, подумайте о вашем скорректированном индексе.
SQL-сервер может найти область для запрашиваемого TenantId. Но затем он должен прочитать все записи для этого TenantId и проверьте, есть ли CreateDate находится в диапазоне, и если это так, он должен проверить, CreatedByID удовлетворяет условиям вашего запроса. Это может быть довольно много строк, в которых требуются эти проверки, в зависимости от размера таблицы и распределения данных.

Прежде всего, убедитесь, что вы сбрасываете кэшированный план для этого запроса между созданием индексов. Ядерный вариант - очистить кеш ( DBCC FREEPROCCACHE ), но вы также можете найти дескриптор плана и просто выбрать конкретный. Я также рекомендовал бы отбрасывать некластеризованные индексы между экспериментами с ними - если у вас есть три индекса в этой таблице, все они пытаются ускорить один и тот же запрос, это не лучшая ситуация.

Размышляя о создании индексов, имейте в виду, что предложения по созданию индексов, которые предоставляет вам SQL, имеют ограниченную ценность. SQL обычно понимает это правильно, когда говорит: «Я мог бы лучше поработать с индексом здесь», но на самом деле у него нет хорошего способа сказать вам точный индекс, который лучше всего соответствует вашим потребностям.

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

В общем, вы хотите иметь четкое представление о запросе, который вызывает необходимость в индексе, а затем создать индекс, соответствующий этому запросу. Большинство запросов принимают форму обращения к некоторому конкретному набору записей, поэтому столбцы в индексе располагаются в порядке от наиболее подходящих до наименее пригодных для поиска желаемых данных. Другими словами, если один столбец может исключить 95% всех возможных результатов, а другой столбец может исключить 20% результатов, поместите столбец 95% первым.

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

Глядя на ваш запрос, не зная ваших данных, я предполагаю, что довольно хороший индекс для него будет:

CREATE NONCLUSTERED INDEX [IX_Company_Tenant] 
ON [dbo].[Company] ([CreatedDate],[CreatedByID],[TenantId])

Вот хорошая статья в блоге, которая объясняет это более подробно - https://www.brentozar.com/archive/2019/10/how-to-think-like-the-sql-server-engine-adding-a-nonclustered-index/