SQL Server, почему индекс не используется - PullRequest
3 голосов
/ 01 декабря 2011

У меня есть следующая таблица в базе данных SQL Server 2008:

CREATE TABLE [dbo].[Actions](
    [ActionId] [int] IDENTITY(1,1) NOT NULL,    
    [ActionTypeId] [int] NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [Description] [nvarchar](1000) NOT NULL,
    [Comment] [nvarchar](500) NOT NULL,
    [Created] [datetime] NOT NULL,
    [Executed] [datetime] NULL,
    [DisplayText] [nvarchar](1000) NULL,    
    [ExecutedBy] [int] NULL,
    [Result] [int] NULL
)   
CONSTRAINT [PK_Actions] PRIMARY KEY CLUSTERED 
(
    [CaseActionId] ASC
)
) ON [PRIMARY]

GO


CREATE NONCLUSTERED INDEX [IX_Actions_Executed] ON [dbo].[Actions] 
(
    [Executed] ASC,
    [ExecutedBy] ASC
)

Есть 20 000 строк с датой выполнения, равной 2500-01-01, и 420 000 строк с датой выполнения <2500-01-01. </p>

Когда я выполняю запрос

select CaseActionId, Executed, ExecutedBy, DisplayText from CaseActions
where Executed='2500-01-01'  

В планах запросов показано, что сканирование кластерного индекса на PK_Actions выполняется, а индекс IX_Actions_Executed вообще не используется.

Какая смешная у меня пропущенная подсказка с указанием

/* The Query Processor estimates that implementing the following index could improve the query cost by 99.9901%.
*/

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[Actions] ([Executed])

Но индекс уже есть.

Почему индекс не используется, если он выберет 5% данных?

1 Ответ

4 голосов
/ 01 декабря 2011

Скорее всего, оптимизатор запросов просто видит, что вы также выбираете DisplayText - поэтому для каждой из 20 000 строк, найденных в индексе NC, должен быть поиск ключа в кластеризованный индекс для получения этих данных - и поиск ключей - это дорогие операции! Так что, в конце концов, может быть проще и эффективнее сканировать индекс кластера сразу.

Бьюсь об заклад, если вы выполните этот запрос здесь:

select CaseActionId, Executed, ExecutedBy
from CaseActions
where Executed='2500-01-01'

тогда будет использоваться индекс NC

Если вам действительно нужен DisplayText, и этот запрос вы будете часто выполнять, возможно, вам следует включить этот столбец в индекс в качестве дополнительного столбца на уровне листа:

DROP INDEX [IX_Actions_Executed] 

CREATE NONCLUSTERED INDEX [IX_Actions_Executed] 
ON [dbo].[Actions]([Executed] ASC, [ExecutedBy] ASC)
INCLUDE([DisplayText])

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

Пропущенные подсказки к индексам иногда вводят в заблуждение - есть также известные ошибки, которые приводят к тому, что SQL Server Mgmt Studio постоянно рекомендует индексы, которые уже существуют ..... не ставьте слишком много своих денег на эти индексные подсказки!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...