[译]SQL Passion Week 8: 包含索引与临界点

Week 8: Covering Indexes & Tipping Point
 
  当我们需要根据非聚集索引的字段作为条件来检索数据, 但返回的字段又不包含在非聚集索引中. 这种情况, 需要走两遍索引(一遍非聚集,一遍聚集),有时候这样做并不是很有效率,我们可以用Covering Index(包含索引)来解决.
  
  Covering Indexes
 
  包含索引也是非聚集索引的一种, 唯一的不同是索引中包含了请求字段的值. 我们通过例子来了解:
  下面的查询将会使用Bookmark lookup, 因为PostalCode 并不是非聚集索引IX_Address_StateProvinceID的一部分, 
 
  
SELECT
   AddressID,
   PostalCode
FROM Person.Address
WHERE StateProvinceID = 42
GO

 

  这个查询产生了18个逻辑读.

 

  下面我们创建一个包含了PostalCode值的包含索引, 

  

CREATE NONCLUSTERED INDEX idxAddress_StateProvinceID ON
Person.Address (StateProvinceID)
INCLUDE (PostalCode)
GO

  再重新执行查询, 此时就变成了Index Seek(NonClustered)操作,逻辑读降成了2个,非常大的性能提升.

 

  

  Tipping Point
 
  有些情况,SQL Server能判断使用Bookmark Lookup耗能过高而弃用, 改为整个表的Scan操作. 这个判断的依据我们称之为临界点(Tipping Point).
  
graphic
 
 
  在你需要查询的页数占据1/4到1/3之间时,会触发临界点. 但是没有准确的数字,因为每页包含的记录数并不相同.
 
  举个例子,我们有个表每条记录都是400bytes的大小,也就是每页能存储20条记录.然后在value列上建一个非聚集索引,下面的查询使用Bookmark Lookup返回了1061行
                                                                                                                                                                                                                                                                            
SELECT * FROM Customers
WHERE Value < 1062
GO 

  而如果多返回一行,这个查询就过了临界点,改成Scan了这个表

SELECT * FROM Customers
WHERE Value < 1063
GO

  两个几乎一样的查询,却是不同的执行计划.有时候这会导致一些严重的问题,因为我们不再有稳定的计划.

  

  Summary

  我们学习了SQL Server中的不同类型的索引,这些索引都可以提高数据库的读性能,但副作用是会降低写性能.每当我们执行insert,update,delete操作时,都有可能导致索引的维护工作.

  因此我们需要根据数据库的读与写的工作量来评估索引战略. 

                                                                                                                 
  
 
  

  

posted @ 2016-01-04 15:58  AlphaQcode  Views(170)  Comments(0Edit  收藏  举报