新索引的使用不符合预期

时间:2018-03-07 11:30:43

标签: sql-server sql-server-2008 indexing

在我的SQL Server数据库中,我有一个请求表,其中requestID(int)为Identity,PK和Clustered索引。表中大约有30个其他列。

我正在使用Entity Framework来访问数据库。

有一个名为GetRequestByID(int requestID)的函数,它使用内部联接从Requests表和相关表中提取所有列。

最近,为了减少不需要的数据量,我创建了两个额外的函数GetRequestByID_LiteGetRequestByID_EvenLiter,它们返回的列数较少,并替换了代码中的所有相关调用。 对于每个函数,我通过requestID创建了一个相应的非聚集索引,并且只包含每个函数所需的列。

一小时后,我看到的第一件事就是过程消耗的内存急剧减少 当我运行SYS.DM_DB_INDEX_USAGE_STATS时,我看到以下新索引:

_index_for_GetRequestByID_Lite - 0寻求,422次扫描,0次查找,49次更新 _index_for_GetRequestByID_EvenLiter - 0次搜索,0次扫描,0次查找,51次更新

我的问题是为什么这么多次扫描而没有寻找_index_for_GetRequestByID_Lite? 如果索引不包含所需的所有列,那么SQL Server为什么不使用聚簇索引呢? 为什么_index_for_GetRequestByID_EvenLiter根本没被使用(毫无疑问,函数GetRequestByID_EvenLiter被大量调用)?

此外,当我运行等同于GetRequestByID_EvenLiter的SQL查询时,聚集索引将用于执行计划而不是_index_for_GetRequestByID_EvenLiter

谢谢。

1 个答案:

答案 0 :(得分:2)

SQLServer可能没有发现您的索引在成本方面有效。

见下面的例子

create table
test
(
col1 int primary key,
col2 int,
col3 int,
col4 varchar(10),
col5 datetime
)

insert into test
select number,number+1,number+2,number+5,dateadd(day,number,getdate()) 
from numbers

让我们创建一个索引

create index nc_Col2 on test(col2)
include(Col3,col4)

现在,如果我们运行如下的查询

select * from test 
where col2>4

并查看执行计划成本......

enter image description here

您可能认为sqlserver应该使用上面的索引,但它没有。现在让我们观察强制sqlserver使用该索引的成本

select * from test with (index (nc_col2))
where col2>4

enter image description here

总之,您的索引可能未被使用的原因可能是由于

  • 与其他现有的可能性相比,它不具成本效益
  • 您的索引效率不高,如我的示例所示(我选择*且索引只有三列)

还有一些概念,如分配扫描,顺序扫描,但总的来说,SQL必须相信您的索引成本更低。请查看以下链接,了解如何改进成本核算

进一步阅读:
Inside the Optimizer: Plan Costing
https://dba.stackexchange.com/a/23716/31995