在数据库中,索引的含义与平常意义上的“索引”一词并没有多大区别,与书中的索引同样,数据库中的索引使您能够快速找到表中的特定信息。索引包含从表中一个或多个列生成的键,以及映射到指定数据的存储位置的指针,也就是说索引由键和 指针组成。它是用于提升数据库表数据访问速度的数据库对象。html
数据库文件存储是已页为存储单元的,一个页是8K(8192Byte),一个页就能够存放N行数据。咱们经常使用的页类型就是数据页和索引页。一个页中除了存放基本数据以外还须要存放一些其余的数据,如页的信息、偏移量等,以下图所示。数据库
虽然SQLServer是以页为单位存储数据,可是其分配空间是以一个盘区为单位的(8个页=64K),这样作的目的主要是为提升I/O的性能。缓存
一条索引记录中包含的基本信息包括:键值 + 逻辑指针。网络
SQLServer中使用页为存储单元的,那么在创建索引时,其索引节点就是页了,而后树的键值就是存放到这些页(节点)中的。就是说表中的数据行就是存放到页上的,一个表有多个页构成,这些页以树的结构存放。架构
B树即二叉搜索树,全部非叶子节点最低拥有两个子节点,基本信息以下图所示。都是小的元素放左边,大的元素放右边。好比说要查找某个元素,其时间复杂度就对应该元素的深度,如要查询9,从根节点开始,只要比较三次就找到他了,其查询效率是很是高的。数据库设计
子节点:最多两个子节点(指针分别指向Left和Right)布局
阶数(节点子节点个数):2性能
深度:就是层数,各个叶子节点不必定同样,如节点21的深度为4,40的深度为3测试
B-树是一中多路搜索树,其阶数能够自定义(>2),是不少数据及文件系统应用的一种索引结构,基本特征如:优化
1) 阶数(M)>2,即孩子数量大于2个
2) 每一个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
3) 非叶子结点上的多个关键字是按照顺序排列的:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
4) 全部叶子节点都位于同一层,所以叶子节点的深度都是同样的
5) 非叶子结点的关键字个数=指向儿子的指针个数-1;
6) 非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;
以下图是一个三阶的B-树,节点[18]有两个指针分别指向其2个子节点。
这时若是要插入一个值17,其处理步骤:
1) 从根节点进入,17小于22,进入左边的节点[18];
2) [18]不是叶子节点,继续向下搜索,17小于18,进入其左边的子节点[12,16];
3) [12,16]为叶子节点,插入到该节点;
4) 节点[12,16,17]元素大于2了(3阶树的节点关键字数量应>3/2-1,<3-1),所以该节点须要分裂,分裂中间的元素16到父节点18中去;
5) 12,17分裂成了两个子节点了;
分裂后的效果以下图
以上图片效果来自一个外国大学里面的的在线版B-树的测试,网站:http://www.cs.usfca.edu/~galles/visualization/BTree.html ,你们能够去这个网站测试,效果很直观,外国人就是牛。本人之前用C#+GDI实现过相似的效果,结果仍是能够的,就是当树太大的时候,布局很差处理了。
B+树是B-树的变体,也是一种多路搜索树,一棵m 阶的B+树和m 阶的B-树的差别在于:
l 非叶子节点的子节点和其关键字相同,即节点有三个元素(关键字),他就确定有三个子节点;
l 非叶子节点的子节点P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间);
l 全部叶子节点增长一个链指针;
l 全部关键字的数据都在叶子节点中;
以下图所示,图片来自网络(http://www.cnblogs.com/chjw8016/archive/2011/03/08/1976891.html)。
汇集索引是根据数据行的键值在表中排序存储数据行。索引定义中包含汇集索引列。每一个表只能有一个汇集索引。只有当表包含汇集索引时,表中的数据行才按排序顺序存储。若是表具备汇集索引,则该表称为汇集表。集索引决定了表数据的存储顺序,若是表没有汇集索引,则其数据行存储在一个称为堆的无序结构中。
对于某个汇集索引,索引指向该汇集索引某个特定分区(数据页)的顶部。SQL Server 将在索引中向下移动以查找与某个汇集索引键对应的行。缘由是汇集索引的索引顺序就是数据排列顺序。
非汇集索引并非在物理上排列数据,即索引中的逻辑顺序并不等同于表中行的物理顺序,索引是指向表中行的位置的指针,这些指针自己是有序的,经过这些指针能够在表中快速定位数据。
因为非汇集索引数据存储时无序的,因此在非汇集索引中指针包含数据行在数据页中的偏移量。即指针由 数据页 + 数据行偏移量 组成。
若是在删除命令的Where子句中包含的列上,建有非汇集索引,那么该非汇集索引将被用于查找数据行的位置,数据删除以后,位于索引叶子上的对应记录也将被删除。若是该表上有其它非汇集索引,则它们叶子结点上的相应数据也要删除
汇集索引和非汇集索引的根本区别是数据记录的排列顺序和索引的排列顺序是否一致,汇集索引表记录的排列顺序与索引的排列顺序一致,优势是查询速度快,由于一旦具备第一个索引值的纪录被找到,具备连续索引值的记录也必定物理的紧跟其后,从而缩小了搜索范围,对于返回某一范围的数据效果最好。
汇集索引的缺点是对表进行修改速度较慢,这是为了保持表中的记录的物理顺序与索引的顺序一致,而把记录插入到数据页的相应位置,必须在数据页中进行数据重排,下降了执行速度。
非汇集索引指定了表中记录的逻辑顺序,数据记录的物理顺序和索引的顺序不一致,汇集索引和非汇集索引都采用了B树的结构,但非汇集索引的叶子层顺序并不与实际的数据页相同,而采用指向表中的记录在数据页中位置的方式。非汇集索引比汇集索引层次多,添加记录不会引发数据顺序的重组。在有大量不一样数据的列上创建非汇集索引,能够提升数据的查询和修改速度。
在对汇集索引列查询时,汇集索引的速度要比非汇集索引速度快。
在对汇集索引列排序时,汇集索引的速度要比非汇集索引速度快。可是若是数据量比较大时,如10万以上,则两者的速度差异不明显。
在建立索引时要作到三个适当,即在适当的表上、适当的列上建立适当数量的索引。虽然这能够经过一句话来归纳优化的索引的基本准则,可是要作到这一点的话,须要作出很大的努力。具体的来讲,要作到这个三个适当有以下几个要求。
虽然给表建立索引,能够提升查询的效率。可是须要注意的是,索引也须要必定的开销的。为此并非说给全部的表都建立索引,那么就能够提升数据库的性能。这个认识是错误的。给全部的表都建立了索引,那么其反而会给数据库的性能形成负面的影响。由于此时滥用索引的开销可能已经远远大于由此带来的性能方面的收益。因此,数据库管理员首先须要作到,为合适的表来创建索引,而不是为全部的表创建索引。
通常来讲,不须要为比较小的表建立索引。由于即便创建了索引,其性能也不会获得很大的改善。相反索引创建的开销,如维护成本等等,要比这个要大。也就是说,付出的要比获得的多,显然违反常理。
另外,就是对于超大的表,也不必定要创建索引。有些表虽然比较大,记录数量很是的多。可是此时为这个表创建索引并必定的合适。对于一些超大的表,创建索引有时候每每不可以达到预计的效果。并且在大表上创建索引,其索引的开销要比普通的表大的多。那么究竟是否给大表创建索引呢?主要是看两个方面的内容。首先是须要关注一下,在这张大表中常常须要查询的记录数量。通常来讲,若是常常须要查询的数据不超过10%到15%的话,那就没有必要为其创建索引的必要。由于此时创建索引的开销可能要比性能的改善大的多。若是数据库管理员须要得出一个比较精确的结论,那么就须要进行测试分析。
列的特色不一样,索引建立的效果也不一样。须要了解为哪些列建立索引能够起到事半功倍的效果。同时也须要了解为哪些列建立索引反而起到的是事倍功半的效果。
索引设置的是否恰当,不只跟数据库设计架构有关,并且还跟企业的经济业务相关。虽然一开始已经作了索引的优化工做。可是随着后来经济数据的增长,这个索引的效果会愈来愈打折扣。因此须要隔一段时间,对数据库的索引进行优化。该去掉的去掉,该调整的调整,以提升数据库的性能。
一般来讲,表的索引越多,其查询的速度也就越快。可是,表的更新速度则会下降。这主要是由于表的更新同时也是索引的更新。到底在表中建立多少索引合适,就须要在这个更新速度与查询速度之间取得一个均衡点。如对于一些数据仓库或者决策型数据库系统,其主要用来进行查询。相关的记录每每是在数据库初始化的时候导入。此时,设置的索引多一点,能够提升数据库的查询性能。同时由于记录不怎么更新,因此索引比较多的状况下,也不会影响到更新的速度。相反,若是那些表中常常须要更新记录,如一些事务型的应用系统,数据更新操做是屡见不鲜的事情。此时若是在一张表中创建过多的索引,则会影响到更新的速度。因为更新操做比较频繁,因此对其的负面影响,要比查询效率提高要大的多。此时就须要限制索引的数量,只在一些必要的字段上创建索引。
总之,在适当的表、适当的列上创建适当的索引。具体的索引优化内容仍是须要在平常工做中继续体会与总结。
下面的表总结了什么时候使用汇集索引或非汇集索引:
动做描述 |
使用汇集索引 |
使用非汇集索引 |
列常常被分组排序 |
应 |
应 |
返回某范围内的数据 |
应 |
不该 |
一个或极少不一样值 |
不该 |
不该 |
小数目的不一样值 |
应 |
不该 |
大数目的不一样值 |
不该 |
应 |
频繁更新的列 |
不该 |
应 |
外键列 |
应 |
应 |
主键列 |
应 |
应 |
频繁修改索引列 |
不该 |
应 |
注:具体参考数据库\聚簇索引和非聚簇索引.ppt