【问题标题】:index access by non-clustered index非聚集索引的索引访问
【发布时间】:2010-08-10 23:29:56
【问题描述】:

如果我有两个数据表。一个有聚集索引 CINDEX,另一个是堆 HEAP。

两者在同一列上也有一个非聚集索引 - SEARCHCOL

假设我的聚集索引列的大小与 rowid 相同,因此两个非聚集索引的深度相同。

这将花费更少的 I/O 来获取表行...

a) SELECT * FROM CINDEX WHERE SEARCHCOL = :1

b) SELECT * FROM HEAP WHERE SEARCHCOL = :1

选择 a 或 b 解释为什么 陈述任何假设

【问题讨论】:

    标签: sql-server optimization


    【解决方案1】:

    如果Searchcol 有足够的选择性,那么计划应该对非聚集索引(两者相同)进行预期的查找,然后查找聚集索引或堆,以获取所有列以满足* 投影。与 BTree 查找(必须命中 1-2 个非叶子页面以降落在包含该行的叶子页面上)相比,此稍后的查找将在堆中更快(按 page:slot 直接搜索)如果堆行是没有移动。如果堆行被移动,则查找必须在新页面上追逐转发指针,这意味着新的逻辑读取 IO,依此类推,直到找到该位置(如果移动多次)。所以一般来说,一个堆会节省 1-2 个逻辑读取 IO(查找中的非叶子部分)。

    如果 SEARCHCOL 没有足够的选择性并且查询命中 Tipping Point,那么所有的赌注都将被取消,因为一个计划会按键顺序进行聚集索引扫描,而另一个计划会按分配顺序进行堆扫描(他们会最终的 IO 大致相同)。

    但我必须警告,在决定堆还是 BTree 时,这种细节测量(1-2 页 IO)是不健康的。我的看法是总是选择 BTree,除非有明确的理由不这样做。明确的原因通常是 INSERT 性能(这是 HEAP 在 BTree 周围运行的地方),这意味着 ETL 数据加载场景,其中数据被加载到堆中以获得快速上传性能,然后堆变成聚集索引并添加将操作切换到大事实表中。

    【讨论】:

    • 也许这是普通 SQL Server 数据库中的一个小细节……但我靠调优高性能数据库中的一两个 IO 为生。我认为应该有一个关于问题的单选按钮......(x)我需要一个企业大男孩的答案或()我有一个只有少数用户的部门应用程序,没有真正的 SLA。但我再次感谢你证实了我的怀疑。行越宽,每个叶子块的行越少,b-tree 表与堆越深,出现的“不显眼” IO 越多,数十亿行越深……所以宽或长表得到相对来说越来越差了。
    • 需要明确的是,这不是单个查询中的一两个 IO……而是该查询每分钟执行 10,000 次的时候。
    • 很公平。比较使用聚集索引与堆组织的表:msdn.microsoft.com/en-us/library/cc917672.aspx
    • Remus,我在网上阅读了很多文章,其中很多都充满了无端的断言。一些文章说,CI 让一切变得更快……臭名昭著的 FASTER = TRUE 配置设置总是正确的。所以我试图从神话中梳理出事实。我打算发布一个很长的多部分问题,但我认为这对 SO 不起作用。所以,我发布了连续的问题,一个建立在前一个的基础上。
    • SO 这里有一个强大的社区,我希望你能得到答案。有时虽然事情并非非黑即白,但答案往往是“视情况而定”......
    猜你喜欢
    • 2013-08-07
    • 2021-01-14
    • 2020-08-04
    • 2021-09-07
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 2014-08-27
    相关资源
    最近更新 更多