简体   繁体   English

SQL Server为什么不使用索引

[英]SQL Server why index is not used

I have a following table in SQL Server 2008 database: 我在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
)

There are 20 000 rows which has Executed date equal to '2500-01-01' and 420 000 rows which has Executed date < '2500-01-01'. 有20 000行执行日期等于'2500-01-01'和420 000行执行日期<'2500-01-01'。

When I execute a query 当我执行查询时

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

the query plans shows that the clustered index scan on PK_Actions is performed and the index IX_Actions_Executed is not used at all. 查询计划显示执行PK_Actions上的聚簇索引扫描,并且IX_Actions_Executed不使用索引IX_Actions_Executed

What funny I got missing index hint which says 我错过了什么有趣的索引提示说

/* 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])

But the index is already there. 但该指数已经存在。

Why the index is not used if it would select 5% of the data ? 如果选择5%的数据,为什么不使用索引?

Most likely, the query optimizer just sees that you're selecting DisplayText as well - so for each of the 20'000 rows found in the NC index, there would need to be a key lookup into the clustered index to get that data - and key lookups are expensive operations! 最有可能的是,查询优化器只是看到你正在选择DisplayText - 所以对于NC索引中找到的20'000行中的每一行,都需要对聚集索引进行密钥查找才能获得该数据 - 以及密钥查找是昂贵的操作! So in the end, it might just be easier and more efficient to scan the clustere index right away. 因此,最终,立即扫描clustere索引可能会更容易,也更有效。

I bet if you run this query here: 我打赌如果你在这里运行这个查询:

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

then the NC index will be used 然后将使用NC索引

If you really need the DisplayText and that's a query you'll run frequently, maybe you should include that column in the index as an extra column in the leaf level: 如果你确实需要DisplayText并且这是一个经常运行的查询,那么你可能应该在索引中将该列作为叶级别的额外列包含在内:

DROP INDEX [IX_Actions_Executed] 

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

This would make your NC index a covering index , ie it could return all columns needed for your query. 这将使您的NC索引成为覆盖索引 ,即它可以返回查询所需的所有列。 If you run your original query again with this covering index in place, I'm pretty sure SQL Server's query optimizer will indeed use it. 如果你使用这个覆盖索引再次运行原始查询,我很确定SQL Server的查询优化器确实会使用它。 The probability that any NC index will be used is significantly increased if that NC index is a covering index, eg some queries can get all their columns they need from just the NC index, without key lookups. 如果NC索引是覆盖索引,则任何NC索引将被使用的概率显着增加,例如,一些查询可以从NC索引获得他们需要的所有列,而无需密钥查找。

The missing index hints are a bit misleading at times - there are also known bugs leading to SQL Server Mgmt Studio to continously recommendation indices that are already in place..... don't bet too much of your money on those index hints! 丢失的索引提示有时会有点误导 - 还有一些已知的错误导致SQL Server Mgmt Studio连续推荐已经存在的索引.....不要在这些索引提示上下注过多的钱!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM