数据库索引比如是一本书前面的目录,能加快数据库的查询速度。
例如这样一个查询:select * from table1 where id=44。若是没有索引,必须遍历整个表,直到ID等于44的这一行被找到为止;有了索引以后(必须是在ID这一列上创建的索引),直接在索引里面找44(也就是在ID这一列找),就能够得知这一行的位置,也就是找到了这一行。可见,索引是用来定位的。
索引分为聚簇索引和非聚簇索引两种,聚簇索引 是按照数据存放的物理位置为顺序的,而非聚簇索引就不同了;显然在一个基本表上最多只能创建一个聚簇索引。创建聚簇索引后,更新该索引列上的数据时,每每致使表中记录的物理顺序的变动,代价较大,所以对于常常更新得列不宜创建聚簇索引,聚簇索引能提升多行检索的速度,而非聚簇索引对于单行的检索很快。创建一个聚簇索引如:算法
create cluster index id on Student(id);sql
创建索引的目的是加快对表中记录的查找或排序。
为表设置索引要付出代价的:一是增长了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(由于索引也要随之变更)。数据库
精简来讲,索引是一种结构.在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)存放的,假设我有这样一张表:spa
如今这张表上没有任何索引,也就是以堆存放,我经过在其上加上汇集索引(以B树存放)来展示对IO的减小:.net
在SQL SERVER中,最主要的两类索引是汇集索引和非汇集索引。能够看到,这两个分类是围绕汇集这个关键字进行的.那么首先要理解什么是汇集.
汇集在索引中的定义:
为了提升某个属性(或属性组)的查询速度,把这个或这些属性(称为汇集码)上具备相同值的元组集中存放在连的物理块称为汇集。
简单来讲,汇集索引就是:
在SQL SERVER中,汇集的做用就是将某一列(或是多列)的物理顺序改变为和逻辑顺序相一致,好比,我从adventureworks数据库的employee中抽取5条数据:
当我在ContactID上创建汇集索引时,再次查询:
在SQL SERVER中,汇集索引的存储是以B树存储,B树的叶子直接存储汇集索引的数据:
由于汇集索引改变的是其所在表的物理存储顺序,因此每一个表只能有一个汇集索引.
由于每一个表只能有一个汇集索引,若是咱们对一个表的查询不只仅限于在汇集索引上的字段。咱们又对汇集索引列以外还有索引的要求,那么就须要非汇集索引了.
非汇集索引,本质上来讲也是汇集索引的一种.非汇集索引并不改变其所在表的物理结构,而是额外生成一个汇集索引的B树结构,但叶子节点是对于其所在表的引用,这个引用分为两种,若是其所在表上没有汇集索引,则引用行号。若是其所在表上已经有了汇集索引,则引用汇集索引的页.
一个简单的非汇集索引概念以下:
能够看到,非汇集索引须要额外的空间进行存储,按照被索引列进行汇集索引,并在B树的叶子节点包含指向非汇集索引所在表的指针.
MSDN中,对于非汇集索引描述图是:
能够看到,非汇集索引也是一个B树结构,与汇集索引不一样的是,B树的叶子节点存的是指向堆或汇集索引的指针.
经过非汇集索引的原理能够看出,若是其所在表的物理结构改变后,好比加上或是删除汇集索引,那么全部非汇集索引都须要被重建,这个对于性能的损耗是至关大的。因此最好要先创建汇集索引,再创建对应的非汇集索引.
前面经过对于汇集索引和非汇集索引的原理解释.咱们不难发现,大多数状况下,汇集索引的速度比非汇集索引要略快一些.由于汇集索引的B树叶子节点直接存储数据,而汇集索引还须要额外经过叶子节点的指针找到数据.
还有,对于大量连续数据查找,非汇集索引十分乏力,由于非汇集索引须要在非汇集索引的B树中找到每一行的指针,再去其所在表上找数据,性能所以会大打折扣.有时甚至不如不加非汇集索引.
所以,大多数状况下汇集索引都要快于非汇集索引。但汇集索引只能有一个,所以选对汇集索引所施加的列对于查询性能提高相当紧要.
第二部分 MySQL索引背后的数据结构及算法
这一部分能够参考本博客前面转的一篇MySQL索引背后的数据结构及算法原理(转),为了防止代码重复这里就给出函数调用便可.