回答

收藏

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

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

我从来没有真正理解过这两个索引之间的区别,有人可以解释一下它们之间的区别是什么(性能方面,在db中是怎样的索引结构,在存储方面是怎样的)?
, j1 F$ {# ~  s" e$ K' O5 f: l包含索引" f. r/ d" a0 ~* l  `
CREATE NONCLUSTERED INDEX IX_Address_PostalCode  1 V. c- D2 i1 B+ o2 P8 C
ON Person.Address (PostalCode)
- A. F+ N% j! gINCLUDE (AddressLine1, AddressLine2, City, StateProvinceID);2 W2 K0 j' k. y- @! U3 }! Y+ Q
``正常’‘指数1 ^% I1 j9 R- ]+ ^* k5 o
CREATE NONCLUSTERED INDEX IX_Address_PostalCode  & D3 Y' B' u8 Z) ?! `! ~: {
ON Person.Address (PostalCode, AddressLine1, AddressLine2, City, StateProvinceID);5 }1 x, d, j* g
                ) y5 z+ K' g" y' g1 Y  }
解决方案:
8 N, p6 z# ?, V/ l* ^+ j5 p% n                / \6 b# E: W6 j7 v2 \- R

; N- H' s: w/ O) g$ q( j2 a1 x) F# m0 X  Z" i
                索引的内部存储使用B-Tree结构,由“索引页”(根目录和所有中间页)和“索引数据页”(仅叶子页)组成。* V! |* [2 l+ z) B/ V

7 S$ R! Y( w" J# j请注意,请勿将“索引数据页”与“数据页”(聚集索引的叶页)混淆,“数据页”存储实际数据的大多数列。
# s; K7 L. U7 |! ?& w# \' T  I5 X; L4 N. g2 V2 }
仅索引列存储在索引页面上。
+ `/ J6 K8 E9 H8 G: `2 R8 S通过在该INCLUDE部分中放置一些列,每个索引键上存储的数据更少。
  Y9 C& I  m) M! u9 o意味着需要更少的页面来保存索引键。(这 使得更容易将这些常用页面在内存中的缓存时间更长。 )
& G+ g) B3 d  o2 Y+ V3 x- i并且树中的级别可能更少。( 在这种情况下,性能提升可能会更大,因为每个树级别遍历都是另一个磁盘访问。 )
; Q" F9 j) P3 n# j$ W$ {
4 R( A& g4 }) {; t8 x/ d0 V
使用索引时,索引键用于在索引页面中导航到正确的索引数据页面。
% K- O3 P, A% N如果索引包含INCLUDE列,则该数据将在查询需要时立即可用。* ]) \1 Q4 E2 T9 K' G0 Z
如果查询要求索引键或列中没有可用的INCLUDE列,则需要对聚集索引中的正确行(或堆,如果未定义聚集索引)进行额外的“书签查找”。! v0 ]: u" r, u0 _4 }$ \
2 A- ^  X1 N6 Q  v" N5 Y
需要注意的一些事情有望解决您的一些困惑:
/ A& N( j5 q  t7 q) K如果索引的键和查询中的过滤器的 选择性 不够,则该索引将被忽略(无论您的INCLUDE列中有什么内容)。* L# V0 f% Q* b  D4 E* s
您创建的每个索引都有INSERT和UPDATE语句的开销。对于“更大”的索引更是如此。(更大也适用于INCLUDE列。)
" ?2 a" E! ~" V3 I! s6 @5 Q* J: q  U$ o因此,尽管从理论上讲您可以使用include列创建大量大索引来匹配访问路径的所有排列:这会适得其反。  d! H" V* A' s/ x6 ~1 N8 |1 Q! k+ Q
9 k" A) x* G% d- p; ~* a
值得注意的是,在将INCLUDE列添加为功能之前:
( D9 {* c! B- u+ d$ n7 d扩展索引键以包括索引/过滤器中不需要的列是常见的索引调整“技巧”。(作为覆盖指数。)% [4 v" f8 _! x2 x4 |
这些列通常在输出列或作为与其他表的联接的参考列中是必需的。
7 y8 [" |+ D- A9 e0 S这样可以避免臭名昭著的“书签查询”,但是具有使索引“比严格必要的”更宽的缺点。3 ?2 d3 @: Y' R2 Z' K
实际上,索引中较早的列通常已经标识了一个 唯一行, 这意味着如果没有“避免书签查找”的好处,那么额外包含的列将是完全多余的。3 ?8 E3 d" `" ~8 K" n. N  e
INCLUDE 列基本上可以更有效地提供相同的好处。3 b+ }* d/ V7 }! [; i3 w
. r# X5 s; l* L
注意: 有一点很重要。INCLUDE如果您习惯于始终将查询编写为,这通常是您从索引中的列中获得零收益的习惯SELECT *6 z5 P& J. t, \! {3 t; U
...。通过返回 所有列, 您基本上可以确保在任何情况下都需要书签查找。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则