回答

收藏

具有包含列的索引,有什么区别?

技术问答 技术问答 314 人阅读 | 0 人回复 | 2023-09-14

我从来没有真正理解过这两个索引之间的区别,有人可以解释一下它们之间的区别是什么(性能方面,在db中是怎样的索引结构,在存储方面是怎样的)?
3 }) B) K- ^( G# e# K包含索引
2 N" V7 V5 ]  B" q# r$ dCREATE NONCLUSTERED INDEX IX_Address_PostalCode  9 G0 i& m* ]) n
ON Person.Address (PostalCode)
2 Q: b/ e2 U- P4 Y$ L' X0 y! MINCLUDE (AddressLine1, AddressLine2, City, StateProvinceID);
0 U/ @) W2 j- ]3 ]1 C1 c``正常’‘指数+ d  e; g; h: ?& V* H& `
CREATE NONCLUSTERED INDEX IX_Address_PostalCode  
& b2 y1 z* N$ q: W; A; u+ ZON Person.Address (PostalCode, AddressLine1, AddressLine2, City, StateProvinceID);
" _* L: T1 v- ]  b4 M- c                # S2 F. \; ?+ A) F3 p7 ]! f' n6 t
解决方案:
: e, L( A2 L( V% H0 N1 d- ]0 M: b                % j" F5 D/ G) F) D$ t

6 j: V) b! n9 A, w5 ~( A
5 U3 T& O% U# L  g1 t! Q  T6 n                索引的内部存储使用B-Tree结构,由“索引页”(根目录和所有中间页)和“索引数据页”(仅叶子页)组成。. h$ b1 z0 ?! `: V
$ E% w2 I  x8 y6 b  X& S" T
请注意,请勿将“索引数据页”与“数据页”(聚集索引的叶页)混淆,“数据页”存储实际数据的大多数列。% t2 X4 t' l% _. g- L, d2 b7 C7 `

- n- t7 s$ n3 t# O) [仅索引列存储在索引页面上。
3 k% d% ]/ Y+ ?2 h9 t( T$ L3 {' Z通过在该INCLUDE部分中放置一些列,每个索引键上存储的数据更少。
$ o9 n2 l( O' G& d$ s# v. E/ Q意味着需要更少的页面来保存索引键。(这 使得更容易将这些常用页面在内存中的缓存时间更长。 )
. b) r6 G$ V/ S& F并且树中的级别可能更少。( 在这种情况下,性能提升可能会更大,因为每个树级别遍历都是另一个磁盘访问。 )
1 S/ t" K7 h% z
) @: }- \' b2 b+ M9 }
使用索引时,索引键用于在索引页面中导航到正确的索引数据页面。
: T( o) h8 _2 ]$ R7 X如果索引包含INCLUDE列,则该数据将在查询需要时立即可用。2 H2 e, n& w& m4 t4 ^8 [4 I0 s" U
如果查询要求索引键或列中没有可用的INCLUDE列,则需要对聚集索引中的正确行(或堆,如果未定义聚集索引)进行额外的“书签查找”。
0 u3 i% ], I  P' j% I3 a
2 e: Q1 {6 L& j; b% S2 b
需要注意的一些事情有望解决您的一些困惑:$ |: v& _0 w& o- y1 Z$ F
如果索引的键和查询中的过滤器的 选择性 不够,则该索引将被忽略(无论您的INCLUDE列中有什么内容)。
! _5 y, y3 y+ h: `您创建的每个索引都有INSERT和UPDATE语句的开销。对于“更大”的索引更是如此。(更大也适用于INCLUDE列。)
3 q7 v# ~' B1 Y) n. `$ d- ?* M因此,尽管从理论上讲您可以使用include列创建大量大索引来匹配访问路径的所有排列:这会适得其反。  e4 X4 _9 R" p. c0 ~, J
) M6 \7 l9 k2 @5 o& H
值得注意的是,在将INCLUDE列添加为功能之前:& h/ X3 X; @  v( r
扩展索引键以包括索引/过滤器中不需要的列是常见的索引调整“技巧”。(作为覆盖指数。)5 P" f7 o; F; h' `+ Z
这些列通常在输出列或作为与其他表的联接的参考列中是必需的。( C' m, C5 E6 {: Q' B. X7 G# R( _- v
这样可以避免臭名昭著的“书签查询”,但是具有使索引“比严格必要的”更宽的缺点。6 P- t6 x% ~' U6 ]! |& O& U, c
实际上,索引中较早的列通常已经标识了一个 唯一行, 这意味着如果没有“避免书签查找”的好处,那么额外包含的列将是完全多余的。$ W$ r' {$ A3 [7 ?
INCLUDE 列基本上可以更有效地提供相同的好处。: \$ C. {% u% `. W2 n

! M+ I0 A3 k1 k: B* t4 n4 r* }- A注意: 有一点很重要。INCLUDE如果您习惯于始终将查询编写为,这通常是您从索引中的列中获得零收益的习惯SELECT *
. b3 s) \# E' y* j" y$ u...。通过返回 所有列, 您基本上可以确保在任何情况下都需要书签查找。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则