You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SQL Server中带INCLUDE的非聚集索引:两种创建方式的差异及验证查询

嘿,这个问题问到点子上了!这俩非聚集索引乍一看差不多,但底层结构和适用场景真的有不少门道,我给你掰扯清楚:

两种非聚集索引的核心区别

1. 索引结构本质不同

  • 第一种:CREATE NONCLUSTERED INDEX IX_NAME1 ON TABLE1 (A) INCLUDE (B,C)
    你可以理解为,这个索引的「核心排序键」只有A列,B和C是额外「搭车」存在索引叶子节点的附加数据——它们不会参与索引的排序和层级查找逻辑,只是当你通过A找到目标行后,能直接拿到这俩值,不用回表查原数据。
  • 第二种:CREATE NONCLUSTERED INDEX IX_NAME1 ON TABLE1 (A,B,C)
    这里A、B、C全都是索引的「核心键列」,整个索引是严格按照A→B→C的顺序排序构建的。也就是说,索引的每一层(根节点、中间节点、叶子节点)都会存储这三列的值,查询时不仅能用A定位,还能借助B、C的排序特性做更精准的过滤或排序。

2. 存储与维护成本差异

  • 存储体积:第二种索引会更大,因为B、C作为键列,要在索引的所有层级都存一份;而第一种只有A在非叶子节点,B、C只在叶子节点出现,整体体积更小。
  • 维护代价:当你更新B或C的值时,第一种索引完全不受影响(因为它们不是键列);但第二种索引会因为键列变化,需要重新调整索引的排序结构,插入、更新、删除的成本更高。
能体现二者差异的SELECT查询例子

场景1:仅通过A过滤,获取B、C的值(覆盖查询)

SELECT B, C FROM TABLE1 WHERE A = 100;

这时候两种索引都能实现覆盖索引扫描(不用回表),但第一种索引因为非叶子节点更小,IO开销会略低,而且后续修改B/C时不会触发索引重构,长期维护成本更低。

场景2:利用B、C做排序或多列过滤

比如带排序的查询:

SELECT A, B, C FROM TABLE1 WHERE A = 100 ORDER BY B, C;

第二种索引本身就是按A→B→C排好序的,当A=100时,对应的B、C已经是有序状态,数据库直接读取即可,完全不需要额外的Sort操作;而第一种索引里的B、C是无序的,数据库必须先找到所有A=100的行,再对B、C做排序,性能差距很明显。

再比如多列条件过滤:

SELECT A, B, C FROM TABLE1 WHERE A = 100 AND B > 50;

第二种索引可以在A=100的范围内,直接利用B的键列排序快速定位B>50的行;而第一种索引只能先把所有A=100的行捞出来,再逐一检查B的值,效率差了不少。

内容的提问来源于stack exchange,提问作者Popeye The Sailor

火山引擎 最新活动