在我的SQL Server数据库中,我有一个请求表,其中requestID(int)为Identity,PK和Clustered索引。表中大约有30个其他列。
我正在使用Entity Framework来访问数据库。
有一个名为GetRequestByID(int requestID)
的函数,它使用内部联接从Requests表和相关表中提取所有列。
最近,为了减少不需要的数据量,我创建了两个额外的函数GetRequestByID_Lite
和GetRequestByID_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
。
谢谢。
答案 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
并查看执行计划成本......
您可能认为sqlserver应该使用上面的索引,但它没有。现在让我们观察强制sqlserver使用该索引的成本
select * from test with (index (nc_col2))
where col2>4
总之,您的索引可能未被使用的原因可能是由于
还有一些概念,如分配扫描,顺序扫描,但总的来说,SQL必须相信您的索引成本更低。请查看以下链接,了解如何改进成本核算
进一步阅读:
Inside the Optimizer: Plan Costing
https://dba.stackexchange.com/a/23716/31995