2

我有一个名为tbl_event与非聚集索引IDX_Event_FolderIDX_Event_Time定义为数据库表一直没有出现执行计划显示的正下方:的SQL Server非聚集索引在执行计划

查询1:

SELECT * 
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000 
ORDER BY tetime 

Execution Plan for Query 1

查询2:

SELECT * 
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000 

Execution Plan for Query 2

我的问题是,为什么从来没有利用上nobjectid指数?我希望在这些select语句的where子句中指定了nobjectid时,会有索引查找或扫描。我对这种分析的理解是不正确的?

+0

您可以发表包括(!)主键定义在内的表定义吗? – TomTom 2011-02-09 18:20:59

+0

表中有多少行?有多少人的价值是`1410000`? – 2011-02-09 18:26:34

+0

18325170行当前在表中,其中只有大约30个有nobjectid = 1410000 – 2011-02-09 20:09:36

回答

2

您在评论中说,目前有在表18325170行,只有大约30人已经nobjectid = 1410000。

即使您的IDX_Event_Folder索引被禁用,我也不能相信SQL Server会为这一行数量选择此计划,并且行厚度表示它认为它处理的可能是1行而不是18325170!

Plan

所以我敢肯定,你必须有自动更新统计禁用?如果是这样,您将需要手动更新统计信息(或者最好启用此选项)

3

为什么nobjectid上的索引从不使用 ?我希望那里是 索引查找或扫描指定nobjectid 当where子句

一个常见的误解了!

有一点是:因为您使用的是SELECT *,您需要表中的所有数据。所以最终,SQL Server必须返回到实际的数据页面并获取所有值。

当发生索引查找并发现命中时,在这种情况下,SQL Server必须执行书签查找 - 这是一个相当昂贵的操作。

由于这些操作相当昂贵,所以如果可能的话,SQL Server会尽量避免它们 - 因此在很多情况下,将使用表扫描,因为最终这比查找nc索引要快,然后做一个书签查找。

点检查:

  • 如何选择性nobjectid列?这里的这个听起来像是一个或多或少的独一无二的ID--那会很好。如果你碰巧在列上有一个索引,这个索引不是很有选择性,那么查询优化器通常会忽略它(因为它必须检查太多的行,所以表扫描最后更快)

  • 有多少是否在表中?对小的表(少于几千行),它往往要快得多做一个表扫描,从一开始走

而且,从与“RID堆查找”你的第一个执行计划,我会总结你在桌子上没有聚集索引 - 立即添加一个!没有群集密钥(因此具有而不是聚簇表)也减慢了大量操作并降低了非聚集索引的有效性。

尝试在 “NUSE” 列中添加您的聚集索引:

  • 独特
  • 稳定
  • 不断增加

INT IDENTITY是一个完美的候选人 - UNIQUEIDENTIFIER或者非常宽的一组色谱柱是最差的。阅读所有关于Kimberly Tripp's blog

1

选择聚集索引有一些重叠的事情在进行

  • SELECT *意思是“给我所有列”。优化器决定它扫描表格更有用。
  • 唯一有用的索引是订购的时间。它这样做,然后钻到桌子上。
  • 您没有聚簇索引(RID /堆查找显示)
  • nobjectid索引缺乏唯一性将无济于事:它意味着完整的索引扫描。 o为什么在结合SELECT *时使用索引?

如果你有这一点,那么该指数将使用(如扫描)

SELECT nobjectid 
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000 

或者这一点,新指数将最有可能被使用

CREATE NONCLUSTERED INDEX [IDX_Co,bined] 
ON [dbo].[tbl_event]([nobjectid] ASC, tetime) 

SELECT nobjectid, tetime 
FROM tbl_event 
WHERE tbl_nobjectid = 1410000 
ORDER BY tetime 

我建议你阅读这些文章

缺乏聚集索引应该由这些文章中介绍过