SQL SERVER 聚集索引 非聚集索引 区别
转自http://blog.csdn.net/single_wolf_wolf/article/details/52915862
一、理解索引的结构
索引在数据库中的作用类似于目录在书籍中的作用,用来提高查找信息的速度。使用索引查找数据,无需对整表进行扫描,可以快速找到所需数据。微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)。
SQL Server 中数据存储的基本单位是页(Page)。数据库中的数据文件(.mdf 或 .ndf)分配的磁盘空间可以从逻辑上划分成页(从 0 到 n 连续编号)。磁盘 I/O 操作在页级执行。也就是说,SQL Server 每次读取或写入数据的最少数据单位是数据页。
下面我们先简单的了解一下索引的体系结构:
1. 聚集索引结构
在 SQL Server 中,索引是按 B 树结构进行组织的。
聚集索引单个分区中的结构:
--建立UserAddDate聚集索引
CREATE CLUSTERED INDEX [IX_AddDate] ON [User]
(
[AddDate] ASC
)
聚集索引(Clustered Index)特点
- 聚集索引的叶节点就是实际的数据页
- 聚集索引中的排序顺序仅仅表示数据页链在逻辑上是有序的。而不是按照顺序物理的存储在磁盘上
- 行的物理位置和行在索引中的位置是相同的
- 每个表只能有一个聚集索引
- 聚集索引的平均大小大约为表大小的5%左右
2. 非聚集索引结构
非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点:
1. 基础表的数据行不按非聚集键的顺序排序和存储。
2. 非聚集索引的叶层是由索引页而不是由数据页组成。
下图示意了单个分区中的非聚集索引结构:
包含列的索引
通过将包含列(称为非键列)添加到索引的叶级,可以扩展非聚集索引的功能。键列存储在非聚集索引的所有级别,而非键列仅存储在叶级别。
下面举个简单的例子来说明一下聚集索引和非聚集索引的区别:
我们有一本汉语字典,可以把它的正文本身看做是一个聚集索引,它是按照汉字拼音的开头字母排序的,不再需要查找其他目录。当遇到不认识的字时,需要结合“部首目录”和“检字表”, 先找到目录中的结果,然后再翻到您所需要的页码。通过这种方法查到的目录中字的排序并不是真正的正文的排序方法。把这种看做是一个非聚集索引。
另外,请注意每个表只能有一个聚集索引。
--建立UserAddDate非聚集索引
CREATE NONCLUSTERED INDEX [IX_AddDate] ON [User]
(
[AddDate] ASC
)
非聚集索引 (Unclustered Index) 特点
- 非聚集索引的页,不是数据,而是指向数据页的页。
- 若未指定索引类型,则默认为非聚集索引。
- 叶节点页的次序和表的物理存储次序不同
- 每个表最多可以有249个非聚集索引
- 在非聚集索引创建之前创建聚集索引(否则会引发索引重建)
二、选择建立哪种索引
1. 何时创建聚集索引更能提高性能
Clustered Index会提高大多数table的性能,尤其是当它满足以下条件时:
独特, 狭窄, 持续增长的,最好是只向上增加。例如:
- Identity
- Date, identity
- GUID (only when using newsequentialid() function)
2. 非聚集索引提高性能的方法
非聚集索引由于B树的节点不是具体数据页,有时候由于这个原因,会导致非聚集索引甚至不如表遍历来的快。但是,非聚集索引有个特性,如果你要查询的内容,在非聚集索引中以及被覆盖到了,则不需要继续到聚集索引,或者RID(heap结构中的行标识符)中去寻找数据了,这时候就可以很大的提高性能,这就是覆盖面(Covering) 的问题。
由于聚集索引叶子节点就是具体数据,所以聚集索引的覆盖率是100%, 通过提高覆盖面来提高性能的问题也就只有非聚集索引(Nonclustered Indexes)才存在。
当查询中所有的columns都包括在index上时,我们说这 index covers the query. Columns的顺序在此不重要(Select 时候的顺序不重要,但是Index 建立的顺序可得小心了)。
在 SQL Server 2005 中,为了提高这种 Covering 带来的好处,甚至可以通过将非键列添加到非聚集索引的叶级别来扩展非聚集索引的功能。
补充:只有查询在具有高度选择性的情况下,非聚集索引才有优势。
三、使用聚集索引或非聚集索引的场景 (注:优先级依次为推荐,应,不应)
四、主键和聚集索引的比较
以下是一些大众点评网中测试使用的示例:
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
五、使用索引的代价
- 索引需要占用数据表以外的物理存储空间
- 创建索引和维护索引要花费一定的时间
- 当对表进行更新操作时,索引需要被重建,这样降低了数据的维护速度。
引用: http://kb.cnblogs.com/page/144409/
SQL SERVER 聚集索引 非聚集索引 区别的更多相关文章
- SQL Server 解读【已分区索引的特殊指导原则】(3) - 非聚集索引分区
一.前言 在MSDN上看到一篇关于SQL Server 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的 ...
- MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析
文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...
- 数据库索引--------B/B+树、聚集、非聚集、符合索引
摘录自博客:http://www.cnblogs.com/morvenhuang/archive/2009/03/30/1425534.html 一.引言 对数据库索引的关注从未淡出我的们的讨论,那么 ...
- Mysql 索引实现原理. 聚集索引, 非聚集索引
Mysql索引实现: B-tree,B是balance,一般用于数据库的索引.使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度.而B+tree是B-tree的一个变种,My ...
- SQL Server查询性能优化——创建索引原则(一)
索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页 就可以.但是索引对于提高查询性能也不是万能的,也不是建立越多的索 ...
- SQL Server 查询性能优化——创建索引原则(一)(转载)
索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页就可以.但是索引对于提高查询性能也不是万能的,也不是建立越多的索引 ...
- SQL Server 查询性能优化——创建索引原则(一)
索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页就可以.但是索引对于提高查询性能也不是万能的,也不是建立越多的索引 ...
- SQL Server 查询性能优化——创建索引原则
索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页就可以.但是索引对于提高查询性能也不是万能的,也不是建立越多的索引 ...
- SQL Server 解读【已分区索引的特殊指导原则】(2)- 唯一索引分区
一.前言 在MSDN上看到一篇关于SQL Server 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的 ...
随机推荐
- 在javaweb的项目当中实现随机数字的生成
首先,需要在javaweb的项目当中新建一个Servlet文件,然后再web.xml中配置一下: 这样运行的时候就可以通过“http://localhost:8080/Response/Respons ...
- SpringMVC系列之URL匹配问题
一.工程目录 二.web.xml配置文件及与其他文件的关系 三.控制器部分 四.返回值 五.url前后缀 六.项目源代码 http://files.cnblogs.com/files/xujian20 ...
- docker 快速搭建Nexus3
1.拉取镜像 docker pull sonatype/nexus3 2.启动容器 : -p : -p : -v /mnt/gv0/nexus-data:/nexus-data sonatype/ne ...
- 支持AIRPLAY ,DLNA,MIRACAST的HDMI DONGLE
好吧,今天没节操,帮老婆推广一下淘宝的店. 联我影棒 http://item.taobao.com/item.htm?spm=a230r.1.14.132.jqGLCa&id=36476326 ...
- Python六大开源框架对比:Web2py略胜一筹(转)
Python是一门动态.面向对象语言.其最初就是作为一门面向对象语言设计的,并且在后期又加入了一些更高级的特性.除了语言本身的设计目的之外,Python标准库也是值得大家称赞的,Python甚至还自带 ...
- Linux命令 dmesg:分析内核产生的信息
案例一 输出所有的内核开机时的信息 zh@zh:~$dmesg | more 案例二 查找开机的时候硬盘的相关信息
- 跟bWAPP学WEB安全(PHP代码)--SQL注入的一些技巧
背景 模拟环境还是 bWAPP,只不过这个bWAPP的SQL注入有点多,一一写意义不大,在这边就利用这个环境来尝试一些SQL注入的技巧.并研究下PHP的防御代码. 普通的bWAPPSQL注入的简单介绍 ...
- [SQL] 用SQL语句检查CPU和磁盘空间
在MS Sql Server中可以能过以下的方法查询出磁盘空间的使用情况及各数据库数据文件及日志文件的大小及使用利用率: 1.查询各个磁盘分区的剩余空间:Exec master.dbo.xp_fixe ...
- 近期在看的一段JS(谁能看出我想实现什么功能)
示例代码: <script type="text/javascript"> !function(){ var e=/([http|https]:\/\/[a-zA-Z0 ...
- BC32206 错误
出现这种情况的话 排除代码引入dll版本的原因 看下是不是 你之前用net reflector 生成了pdb文件 导致项目引入的版本都是他生成的文件 处理方案就是 用everything 找到这个dl ...