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 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的 ...
随机推荐
- mybatis 之resultType="HashMap" parameterType="list"
<!-- 查询商品仓库信息 --> <select id="loadGoodsStock" resultType="HashMap" para ...
- HTML5和CSS3扁平化风格博客(基础篇)
多学一点总是好的~ 自始至终都觉得的css和html效果比较美观,于是在看慕课网教程时,自己也跟着敲了深爱着的前端代码 这部分分为两部分:①基础篇:http://www.imooc.com/learn ...
- 探求C#.Net中ArrayList与Array的区别
ArrayList与Array的区别概述 ArrayList 是数组的复杂版本.ArrayList 类提供在大多数 Collections 类中提供但不在 Array 类中提供的一些功能.例 ...
- 解决安装laravel/homestead vagrant环境报"A VirtualBox machine with the name 'homestead' already exists."的错误
之前在mac上安装laravel/homestead vagrant虚拟机环境时由于参照的教程是: 每次都必须在~/Homestead目录下边运行vagrant up/halt命令,觉得实在是不方便, ...
- sklearn包学习
1首先是sklearn的官网:http://scikit-learn.org/stable/ 在官网网址上可以看到很多的demo,下边这张是一张非常有用的流程图,在这个流程图中,可以根据数据集的特征, ...
- 【面试题】Python高级开发工程师面试题
线上面试题,有空整理答案,欢迎大家回复答案
- StarUML2 建模工具全平台破解及license验证简要分析
破解方法:找到安装目录下的文件:LicenseManagerDomain.js阅读得知,改软件用rsa加密用户信息,换行为用户信息的分隔符修改以下代码,然后打开软件点击菜单栏中的帮助->输入li ...
- RunAsDate v1.36 突破软件试用30天的工具
http://www.nirsoft.net/utils/run_as_date.html RunAsDate v1.36 - Run a program with the specified dat ...
- Mysql命令行导入sql数据
mysqldump 是在 操作系统命令行下运行的,不是在 MySQL 命令行下运行的. 登陆数据库: 登陆本地mysql : mysql -h localhost -u root -p123456 ...
- 总结一下最近用到的技术(1)--ultraESB
最近项目中方法用到了一些新的东西,由于之前没有用到过,现在总结一下,方便以后查阅,本篇文章介绍ultraESB,接下来的文章会介绍JsonSchema,JsonSchamaValidator,Json ...