理解SQL Server中索引的概念,原理

摘自:http://51even.iteye.com/blog/1490412

简介


在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能。但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索引的概念,需要了解大量原理性的知识,包括B树,堆,数据库页,区,填充因子,碎片,文件组等等一系列相关知识,这些知识写一本小书也不为过。所以本文并不会深入讨论这些主题。

索引是什么


索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。

精简来说,索引是一种结构.在SQL Server中,索引和表(这里指的是加了聚集索引的表)的存储结构是一样的,都是B树,B树是一种用于查找的平衡多叉树.理解B树的概念如下图:

理解为什么使用B树作为索引和表(有聚集索引)的结构,首先需要理解SQL Server存储数据的原理.

在SQL SERVER中,存储的单位最小是页(PAGE),页是不可再分的。就像细胞是生物学中不可再分的,或是原子是化学中不可再分的最小单位一样.这意味着,SQL SERVER对于页的读取,要么整个读取,要么完全不读取,没有折中.

在数据库检索来说,对于磁盘IO扫描是最消耗时间的.因为磁盘扫描涉及很多物理特性,这些是相当消耗时间的。所以B树设计的初衷是为了减少对于磁盘的扫描次数。如果一个表或索引没有使用B树(对于没有聚集索引的表是使用堆heap存储),那么查找一个数据,需要在整个表包含的数据库页中全盘扫描。这无疑会大大加重IO负担.而在SQL SERVER中使用B树进行存储,则仅仅需要将B树的根节点存入内存,经过几次查找后就可以找到存放所需数据的被叶子节点包含的页!进而避免的全盘扫描从而提高了性能.

下面,通过一个例子来证明:

在SQL SERVER中,表上如果没有建立聚集索引,则是按照堆(HEAP)存放的,假设我有这样一张表:

现在这张表上没有任何索引,也就是以堆存放,我通过在其上加上聚集索引(以B树存放)来展现对IO的减少:

理解聚集和聚集索引


在SQL SERVER中,最主要的两类索引是聚集索引和非聚集索引。可以看到,这两个分类是围绕聚集这个关键字进行的.那么首先要理解什么是聚集.

聚集在索引中的定义:

为了提高某个属性(或属性组)的查询速度,把这个或这些属性(称为聚集码)上具有相同值的元组集中存放在连续的物理块称为聚集。

简单来说,聚集索引就是:

在SQL SERVER中,聚集的作用就是将某一列(或是多列)的物理顺序改变为和逻辑顺序相一致,比如,我从adventureworks数据库的employee中抽取5条数据:

当我在ContactID上建立聚集索引时,再次查询:

在SQL SERVER中,聚集索引的存储是以B树存储,B树的叶子直接存储聚集索引的数据:

因为聚集索引改变的是其所在表的物理存储顺序,所以每个表只能有一个聚集索引.

非聚集索引

因为每个表只能有一个聚集索引,如果我们对一个表的查询不仅仅限于在聚集索引上的字段。我们又对聚集索引列之外还有索引的要求,那么就需要非聚集索引了.

非聚集索引,本质上来说也是聚集索引的一种.非聚集索引并不改变其所在表的物理结构,而是额外生成一个聚集索引的B树结构,但叶子节点是对于其所在表的引用,这个引用分为两种,如果其所在表上没有聚集索引,则引用行号。如果其所在表上已经有了聚集索引,则引用聚集索引的页.

一个简单的非聚集索引概念如下:

可以看到,非聚集索引需要额外的空间进行存储,按照被索引列进行聚集索引,并在B树的叶子节点包含指向非聚集索引所在表的指针.

MSDN中,对于非聚集索引描述图是:

可以看到,非聚集索引也是一个B树结构,与聚集索引不同的是,B树的叶子节点存的是指向堆或聚集索引的指针.

通过非聚集索引的原理可以看出,如果其所在表的物理结构改变后,比如加上或是删除聚集索引,那么所有非聚集索引都需要被重建,这个对于性能的损耗是相当大的。所以最好要先建立聚集索引,再建立对应的非聚集索引.

聚集索引 VS 非聚集索引


前面通过对于聚集索引和非聚集索引的原理解释.我们不难发现,大多数情况下,聚集索引的速度比非聚集索引要略快一些.因为聚集索引的B树叶子节点直接存储数据,而非聚集索引还需要额外通过叶子节点的指针找到数据.

还有,对于大量连续数据查找,非聚集索引十分乏力,因为非聚集索引需要在非聚集索引的B树中找到每一行的指针,再去其所在表上找数据,性能因此会大打折扣.有时甚至不如不加非聚集索引.

因此,大多数情况下聚集索引都要快于非聚集索引。但聚集索引只能有一个,因此选对聚集索引所施加的列对于查询性能提升至关紧要.

索引的使用


索引的使用并不需要显式使用,建立索引后查询分析器会自动找出最短路径使用索引.

但是有这种情况.当随着数据量的增长,产生了索引碎片后,很多存储的数据进行了不适当的跨页,会造成碎片(关于跨页和碎片以及填充因子的介绍,我会在后续文章中说到)我们需要重新建立索引以加快性能:

比如前面的test_tb2上建立的一个聚集索引和非聚集索引,可以通过DMV语句查询其索引的情况:

SELECT index_type_desc,alloc_unit_type_desc,avg_fragmentation_in_percent,fragment_count,avg_fragment_size_in_pages,page_count,record_count,avg_page_space_used_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID('AdventureWorks'),OBJECT_ID('test_tb2'),NULL,NULL,'Sampled')

我们可以通过重建索引来提高速度:

ALTER INDEX idx_text_tb2_EmployeeID ON test_tb2 REBUILD

还有一种情况是,当随着表数据量的增大,有时候需要更新表上的统计信息,让查询分析器根据这些信息选择路径,使用:

UPDATE STATISTICS 表名

那么什么时候知道需要更新这些统计信息呢,就是当执行计划中估计行数和实际表的行数有出入时:

使用索引的代价


我最喜欢的一句话是”everything has price”。我们通过索引获得的任何性能提升并不是不需要付出代价。这个代价来自几方面.

1.通过聚集索引的原理我们知道,当表建立索引后,就以B树来存储数据.所以当对其进行更新插入删除时,就需要页在物理上的移动以调整B树.因此当更新插入删除数据时,会带来性能的下降。而对于聚集索引,当更新表后,非聚集索引也需要进行更新,相当于多更新了N(N=非聚集索引数量)个表。因此也下降了性能.

2.通过上面对非聚集索引原理的介绍,可以看到,非聚集索引需要额外的磁盘空间。

3.前文提过,不恰当的非聚集索引反而会降低性能.

所以使用索引需要根据实际情况进行权衡.通常我都会将非聚集索引全部放到另外一个独立硬盘上,这样可以分散IO,从而使查询并行.

转载于:https://www.cnblogs.com/wangp2012/archive/2012/11/02/2750947.html

理解SQL Server中索引的概念,原理相关推荐

  1. 理解SQL Server中索引的概念,原理以及其他

    简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...

  2. T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他(看了两次了,转了)

    简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...

  3. 理解SQL SERVER中的分区表(转)

    简介 分区表是在SQL SERVER2005之后的版本引入的特性.这个特性允许把逻辑上的一个表在物理上分为很多部分.而对于SQL SERVER2005之前版本,所谓的分区表仅仅是分布式视图,也就是多个 ...

  4. 理解SQL SERVER中的分区表

    简介 分区表是在SQL SERVER2005之后的版本引入的特性.这个特性允许把逻辑上的一个表在物理上分为很多部分.而对于SQL SERVER2005之前版本,所谓的分区表仅仅是分布式视图,也就是多个 ...

  5. 理解SQL Server中的权限体系(下)----安全对象和权限

    在开始阅读本文之前,请确保你已经阅读过上一篇文章,文章地址: 理解SQL Server中的权限体系(上)----主体 简介 在上一篇文章中,我对主体的概念做了全面的阐述.本篇文章接着讲述主体所作用的安 ...

  6. 理解SQL Server中的锁

    参考文献: T-SQL查询进阶-理解SQL Server中的锁 转载于:https://www.cnblogs.com/xwdreamer/archive/2012/08/19/2646363.htm ...

  7. SQL --理解SQL SERVER中的逻辑读,预读和物理读

    本文转载自:https://www.cnblogs.com/CareySon/archive/2011/12/23/2299127.html 理解SQL SERVER中的逻辑读,预读和物理读 SQL ...

  8. 理解SQL SERVER中的逻辑读,预读和物理读

    在我的上一篇关于SQL SERVER索引的博文,有圆友问道关于逻辑读,预读和物理读的概念.我觉的还是写一篇博文能把这个问题解释清楚. SQL SERVER数据存储的形式 在谈到几种不同的读取方式之前, ...

  9. 如何在SQL Server中索引外键列

    Before going through the main concern of this article, indexing the foreign key columns, let's take ...

最新文章

  1. 十年最强出行变革竟然不是高铁?我们问了2千多人,得到高清有码的答案
  2. 云计算之路-阿里云上:2013年4月7日14:15~18:35服务器故障经过
  3. I am the load of my word
  4. 使用RoundedBitmapDrawable快速生成圆角和圆形图片
  5. 回炉重造-基础规则之类和对象
  6. windows 搭建python 虚拟环境 写程序_Windows下搭建Python虚拟环境
  7. 微信小程序实现轨迹回放
  8. 关于计算机犯罪的英语作文,关于信息安全的英语作文范文
  9. Nginx下配置多个web服务
  10. Python规范神器(PEP8 ),Pylint是代码检查工具
  11. 从数学上证明墨菲定律
  12. 【汇编】intel core cpu中常用的寄存器
  13. 查看elasticserc版本_Elasticsearch版本和客户端介绍
  14. 1972 年 11 月 29 日:雅达利推出投币式街机游戏《乓》
  15. java计算机毕业设计共享充电宝管理系统演示录像2021源码+mysql数据库+系统+lw文档+部署
  16. 记一次奇怪的网络问题
  17. 短视频运营详解:抖音变现目前流行的是七种方式之一电商卖货
  18. 关于Edge被篡改:打开的主页被改动、收藏夹被改动等问题
  19. 计算机网络自顶向下--运输层
  20. 神经网络基础视频教程下载,神经网络训练全过程

热门文章

  1. 用户行为分析面面观之三
  2. html2张图片垂直居中,任意图片实现垂直居中的三种方法(兼容性还不错)
  3. 把ct图像像素值转化为_2020年大型设备上岗证CT技师真题回顾
  4. python selenium 下拉列表_Selenium+Python之下拉菜单的定位
  5. matplotlib 对称图_Python入门向:Matplotlib自救指南篇,从此做图不求人(一)
  6. tomcat ajp协议安全限制绕过漏洞_Apache tomcat 文件包含漏洞复现(CVE20201938)
  7. 人脸对齐(二十)--PRN
  8. 系统学习深度学习(二十四)--WRN
  9. 音视频开发-websocket教程
  10. 从服务器断开并删除套接字