【问题标题】:Why is there a scan on my clustered index?为什么对我的聚集索引进行扫描?
【发布时间】:2010-11-12 18:37:33
【问题描述】:

SQL 2000
NED 表有一个外键到 SIGN 表 NED.RowID 到 SIGN.RowID
SIGN 表有一个外键到 NED 表 SIGN.SignID 到 NED.SignID
RowID 和 SignID 是集群主键,它们是 GUID(不是我的选择)
WHERE 子句是:

FROM
    [SIGN] A   
    INNER JOIN NED N ON A.SIGNID = N.SIGNID  
    INNER JOIN Wizard S ON A.WizardID = S.WizardID   
    INNER JOIN [Level] SL ON N.LevelID = SL.LevelID  
    LEFT JOIN Driver DSL ON SL.LevelID = DSL.LevelID  
        AND DSL.fsDeptID = @fsDeptID  
    INNER JOIN [Character] ET ON S.CharacterID = ET.CharacterID  
    INNER JOIN Town DS ON A.TownID = DS.TownID   
WHERE  
    (A.DeptID = @DeptID OR   
    S.DeptID = @DeptID  
    AND   
    A.[EndTime] > @StartDateTime AND A.[StartTime] < @EndDateTime  
    AND   
    A.NEDStatusID = 2    

为什么这个查询的 SIGN 表上有一个 INDEX SCAN?什么会导致对聚集索引进行索引扫描?谢谢

【问题讨论】:

  • 我要问一下您对这个查询的期望,或者更确切地说,为什么您认为索引扫描在这种情况下是一个问题?
  • 您是否来自其他 DBMS 并希望看到类似散列连接或集群连接的内容?如果是,那么您应该知道在 SQL Server 中,聚集索引只是一个树索引,其中叶节点是数据页。如果您已经知道这一点,请忽略此评论。

标签: sql sql-server clustered-index


【解决方案1】:

聚集索引扫描是 SQL Server 对具有聚集索引的表指定全表扫描的方式。这是因为您在 SIGN 表上没有足够的索引来满足 WHERE 子句,或者因为它决定 SIGN 表足够小(或索引不够选择性),因此表扫描会更有效。

仅通过检查查询,您可能必须索引 DeptID 列以及 StartTime、EndTime 和 NEDStatusID 的某种组合以避免表扫描。如果您询问的原因是因为您遇到了性能问题,您还可以运行索引优化向导(现在是 SQL2005+ 客户端工具中的数据库引擎优化顾问)并让它就创建哪些索引以加快速度提供一些建议提出您的问题。

【讨论】:

    【解决方案2】:

    因为您的 WHERE 子句不针对索引列。

    【讨论】:

    • 这是真的,但它并不能真正解释什么。
    • 但它回答了他的问题。 :)
    • 他没有提到他有什么索引。但这是一个有效且普遍的假设。
    【解决方案3】:

    这是一篇关于 SQL Server 何时达到“临界点”并从索引搜索切换到索引/表扫描的好博文:

    http://www.sqlskills.com/BLOGS/KIMBERLY/post/The-Tipping-Point-Query-Answers.aspx

    您可能希望查看查询的过滤方式,因为临界点通常比人们预期的要少得多。

    【讨论】:

    • 来自文章:“只有不覆盖查询的非聚集索引才有临界点。”
    【解决方案4】:

    如果我没看错的话,你对 SIGN A 表有几个限制:

    WHERE  
            (A.DeptID = @DeptID OR   
            S.DeptID = @DeptID  
            AND   
            A.[EndTime] > @StartDateTime AND A.[StartTime] < @EndDateTime  
            AND   
            A.NEDStatusID = 2
    

    这些限制(如 DeptID、StartTime、EndTime、NEDStatusID)是否已编入索引?这些字段从您的数据集中选择的情况如何?

    如果你有 10 个 mio。 rows 和 NEDStatusID 只有 10 个可能的值,那么对该字段的任何限制都会产生大约。 1米奥。行 - 在这种情况下,SQL Server 执行全表扫描(聚集索引扫描)可能更容易(成本更低),特别是如果它还需要检查同一张表上未编入索引的其他 WHERE 子句, 或者(StartTime、EndTIme 等)。

    马克

    【讨论】:

      猜你喜欢
      • 2015-01-27
      • 2013-11-28
      • 1970-01-01
      • 1970-01-01
      • 2014-12-18
      • 2010-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多