[译]SQL Passion Week 7: 非聚集索引

Week 7: Non-Clustered Indexes
 
 
  上周谈论的是聚集索引,当我们在一个表上定义一个聚集索引,就等于使用索引列来物理排序表. 除此之外,我们还可以在表上创建多个(最高999)非聚集索引.
 
  我们用字典来比喻一下, 字典是按照拼音字母物理排序的(聚集索引), 当我们不知道某个字的读音时怎么查找呢? 利用字的笔画(非聚集索引), 首先在笔画表里根据笔画数找到要找的字的读音, 如果还需要知道更多说明,则根据该字记录的页数来对应具体的解释页.
  SQL Server的非聚集索引也是这样工作的, 查询计划先在页级别的非聚集索引上查找,若要返回的字段不包含在非聚集索引中, 则还需要根据非聚集索引记录的lookup value,再去在聚集索引或heap上找.
  这就是Bookmark Lookup
 
 
  下面的图展示了一个典型的Bookmark Lookup执行计划.
 
  
  SQL Server先在非聚集索引上做了一个Seek操作, 以找到符合条件的行, 另外,又在聚集索引上通过 Key Lookup 操作返回其它select的列. 看起来这个功能很不错, 但实际上Bookmark Lookup非常非常危险.
  它们会引起死锁, 并且性能会受到过期的统计信息的影响, 
 
  在非聚集索引的页级别, 存储了Lookup value,这是一个指向索引表或堆表中物理存储记录所在位置的指针.
 
  如果是heap表,这个指针叫做 Row-Identifier,是一个8byte的值,其中4byte记录的页ID,2byte记录了文件ID,2byte记录了块ID.这些信息组合起来就是记录所在的物理位置.
  如果是聚集表,这个指针就是聚集索引值. 所以我们在挑选索引键值的时候,要注意,如果某个键值也是其它非聚集索引的一部分,这将产生巨大的依赖关系,同时也产生冗余数据.
  
  所以我们在选择索引键的时候,有3个最优的原则
 
  •   Unique
  •   Narrow
  •   Static
  唯一性就不需要解释了, 窄字段的意义在于让你的索引更有效率. 而高度的静态化可以避免产生索引碎片等问题.
 
  
  
原文地址:https://www.cnblogs.com/alphaqcode/p/5098371.html