转自http://blog.csdn.net/single_wolf_wolf/article/details/52915862数据库
1、理解索引的结构ide
索引在数据库中的做用相似于目录在书籍中的做用,用来提升查找信息的速度。使用索引查找数据,无需对整表进行扫描,能够快速找到所需数据。微软的SQL SERVER提供了两种索引:汇集索引(clustered index,也称聚类索引、簇集索引)和非汇集索引(nonclustered index,也称非聚类索引、非簇集索引)。性能
SQL Server 中数据存储的基本单位是页(Page)。数据库中的数据文件(.mdf 或 .ndf)分配的磁盘空间能够从逻辑上划分红页(从 0 到 n 连续编号)。磁盘 I/O 操做在页级执行。也就是说,SQL Server 每次读取或写入数据的最少数据单位是数据页。测试
下面咱们先简单的了解一下索引的体系结构:.net
1. 汇集索引结构code
在 SQL Server 中,索引是按 B 树结构进行组织的。blog
汇集索引单个分区中的结构:排序
--创建UserAddDate汇集索引 CREATE CLUSTERED INDEX [IX_AddDate] ON [User] ( [AddDate] ASC )
汇集索引(Clustered Index)特色索引
2. 非汇集索引结构get
非汇集索引与汇集索引具备相同的 B 树结构,它们之间的显著差异在于如下两点:
1. 基础表的数据行不按非汇集键的顺序排序和存储。
2. 非汇集索引的叶层是由索引页而不是由数据页组成。
下图示意了单个分区中的非汇集索引结构:
包含列的索引
经过将包含列(称为非键列)添加到索引的叶级,能够扩展非汇集索引的功能。键列存储在非汇集索引的全部级别,而非键列仅存储在叶级别。
下面举个简单的例子来讲明一下汇集索引和非汇集索引的区别:
咱们有一本汉语字典,能够把它的正文自己看作是一个汇集索引,它是按照汉字拼音的开头字母排序的,再也不须要查找其余目录。当遇到不认识的字时,须要结合“部首目录”和“检字表”, 先找到目录中的结果,而后再翻到您所须要的页码。经过这种方法查到的目录中字的排序并非真正的正文的排序方法。把这种看作是一个非汇集索引。
另外,请注意每一个表只能有一个汇集索引。
--创建UserAddDate非汇集索引 CREATE NONCLUSTERED INDEX [IX_AddDate] ON [User] ( [AddDate] ASC )
非汇集索引 (Unclustered Index) 特色
2、选择创建哪一种索引
1. 什么时候建立汇集索引更能提升性能
Clustered Index会提升大多数table的性能,尤为是当它知足如下条件时:
独特, 狭窄, 持续增加的,最好是只向上增长。例如:
2. 非汇集索引提升性能的方法
非汇集索引因为B树的节点不是具体数据页,有时候因为这个缘由,会致使非汇集索引甚至不如表遍从来的快。可是,非汇集索引有个特性,若是你要查询的内容,在非汇集索引中以及被覆盖到了,则不须要继续到汇集索引,或者RID(heap结构中的行标识符)中去寻找数据了,这时候就能够很大的提升性能,这就是覆盖面(Covering) 的问题。
因为汇集索引叶子节点就是具体数据,因此汇集索引的覆盖率是100%, 经过提升覆盖面来提升性能的问题也就只有非汇集索引(Nonclustered Indexes)才存在。
当查询中全部的columns都包括在index上时,咱们说这 index covers the query. Columns的顺序在此不重要(Select 时候的顺序不重要,可是Index 创建的顺序可得当心了)。
在 SQL Server 2005 中,为了提升这种 Covering 带来的好处,甚至能够经过将非键列添加到非汇集索引的叶级别来扩展非汇集索引的功能。
补充:只有查询在具备高度选择性的状况下,非汇集索引才有优点。
3、使用汇集索引或非汇集索引的场景 (注:优先级依次为推荐,应,不该)
4、主键和汇集索引的比较
如下是一些大众点评网中测试使用的示例:
CHECKPOINT DBCC DROPCLEANBUFFERS SET STATISTICS IO ON declare @d datetime set @d=getdate() SELECT * FROM User WHERE AddDate>'2008-06-01' AND AddDate<'2008-06-10' select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate()) --(45077 行受影响) --表'User'。扫描计数1,逻辑读取1103 次,物理读取2 次,预读1090 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。 --2543 CHECKPOINT DBCC DROPCLEANBUFFERS SET STATISTICS IO ON declare @d datetime set @d=getdate() SELECT * FROM User WITH (INDEX=IX_AddDate) WHERE AddDate>'2008-06-01' AND AddDate<'2008-06-10' select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate()) --(45077 行受影响) --表'User'。扫描计数1,逻辑读取45165 次,物理读取133 次,预读141 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。 --3860
5、使用索引的代价
引用: http://kb.cnblogs.com/page/144409/