Tom*_*m H 6 sql-server indexing performance sql-server-2005
我有一个相当简单的查询:
SELECT
col1,
col2…
FROM
dbo.My_Table
WHERE
col1 = @col1 AND
col2 = @col2 AND
col3 <= @col3
Run Code Online (Sandbox Code Playgroud)
它表现得非常糟糕,所以我在col1,col2,col3(int,bit和datetime)上添加了一个索引.当我检查查询计划时,它忽略了我的索引.我尝试在每个可能的配置中重新排序索引中的列,它总是忽略索引.当我运行查询时,它执行聚簇索引扫描(表大小介于700K和800K行之间)并需要10-12秒.当我强制它使用我的索引时,它会立即返回.我小心翼翼地清除测试之间的缓存和缓冲区.
我试过的其他事情:
UPDATE STATISTICS dbo.My_Table
CREATE STATISTICS tmp_stats ON dbo.My_Table (col1, col2, col3) WITH FULLSCAN
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么吗?我讨厌在存储过程中放置一个索引提示,但SQL Server似乎无法从中获得这个问题的线索.任何人都知道可能阻止SQL Server识别使用索引的任何其他事情是个好主意吗?
编辑:返回的其中一列是TEXT列,因此使用覆盖索引或INCLUDE将无法正常工作:(
Rem*_*anu 13
你有80万行由col1,col2,col3索引.Col2有点,因此其选择性为50%.Col3是一个范围(<=)的检查,所以它的选择性也大致在50%左右.留下col1.查询是针对通用的参数化计划编译的,因此必须考虑一般情况.如果你有10个不同的col1值,那么你的索引将返回大约800k/10*25%,大约是20k键,在聚簇索引中查找以检索'...'部分.如果你有10k个不同的col1值,那么索引将只返回20个键来查找.正如您所看到的,重要的不是您在这种情况下如何构建索引,而是实际数据.根据col1的选择性,优化器将选择基于聚簇索引扫描的计划(优于20k键查找,每次查找至少 3-5页读取)或基于非聚簇索引的计划(如果col1足够有选择性).在现实生活中,col1的分布也发挥了作用,但进入这一点会使解释过于复杂化.
您可以获得后见之明的好处,并声称该计划是错误的,但该计划是基于编译时可用数据的最佳成本估算.您可以使用提示来影响它(如您所建议的那样提供索引提示,或者像Quassnoi建议的那样优化提示),但是您的查询可能对您的测试集执行得更好,而对于不同的数据集则更糟糕,例如@ col1时的情况= <the value that matches 500k records>.您还可以覆盖索引,从而消除投影列表中需要进行聚簇索引查找的"...",在这种情况下,非聚集索引始终比聚簇扫描更好地进行成本匹配.
金伯利·特里普(Kimberley Tripp)有一篇关于这个主题的博客文章,她称之为" 索引引爆点 ",它解释了如何忽略一个看似完美的候选索引: 一个不包含投影列表且选择性差的非聚集索引将是被视为比集群扫描更昂贵.