聚集索引和非聚集索引
Posted hasagi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聚集索引和非聚集索引相关的知识,希望对你有一定的参考价值。
在讲聚集索引和非聚集索引之前我们先要了解下什么是索引,想要理解索引的原理我们必须了解一种数据结构「平衡树」(非二叉)。当然也有数据库使用哈希桶做数据索引,但是目前主流都以平衡树(B-Tree索引、B+Tree索引)作为数据的默认索引;
B+Tree索引
B+Tree索引是B+Tree在数据库的一种实现方式,也是目前在数据库中使用最频繁的一种索引。B+Tree是从二叉树演化而来,所以在此之前我们必须要先了解二叉查找树、平衡二叉树(AVLTree)和多路平衡查找树(B-Tree);
二叉查找树
二叉树具有以下性质:左子树的键值小于根的键值,右子树的键值大于根的键值。二叉树的搜索相当于一个二分查找。二叉查找能大大提升查询的效率,但是它有一个问题:二叉树是以第一个插入的数据作为根节点,同样的一组数据可能因为顺序不同产生线性链表结构,如下图;
平衡二叉树
为了解决二叉树左右不平衡的问题就有了平衡二叉树,定义是节点的子节点高度差不能超过1,如果因为数据的增删查改导致不平衡则可以通过左旋或右旋解决,但是单单的左右平衡并不能满足数据库库索引的需要;
1、首先树结构中,数据深度决定了检索是的IO次数;
2、查询事件的不稳定导致,有时只需一次IO就查询出数据,而有时则需多次IO才可以;
3、没有利用操作系统和磁盘数据交换的特性以及磁盘的IO预读能力,正常来说操作系统和磁盘间的数据交换是以页(4KB)为单位,也就是说一次数据交换会加载4KB的数据到内存,而平衡二叉树的一个节点只有一个关键词,而这样的IO的操作次数又因为树的高度需要重复多次,极大的浪费系统的性能;
多路平衡二叉树(B-Tree)
首先先有个概念,系统从磁盘读取数据到内存时是以磁盘块为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。其次这里以InnoDB举例,在InnoDB存储引擎中有页(page)的概念,即磁盘管理的最小单位默认是16KB。而往往系统磁盘不可能分配给用户一个完整连续磁盘空间,而是通过多个磁盘块拼接而成,而B-Tree就是了让系统高效的检索磁盘块,通过键值对的形式保存数据;
每个节点占用一个磁盘块,由N个升序关键字和N+1个指针(对应子节点磁盘块地址),如果以上述表结构为例,我们最多只需三次IO操作和内存操作就能获取结果,而且由于内存中的关键字是一个有序表结构,可以利用二分法查找提高效率。B-Tree相对于AVLTree缩减了节点个数,使每次磁盘I/O取到内存的数据都发挥了作用,从而提高了查询效率。
B+Tree
B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,相较于B-Tree有几点不同:
1、非叶子节点只存储键值信息;
2、所有叶子节点之间都有一个链指针;
3、数据记录都存放在叶子节点中;
1、B+Tree是B-Tree的变种,所以B-Tree能解决的问题,B+Tree也能够解决;
2、B+Tree扫库和扫表能力更强,如果我们要根据索引去进行数据表的扫描,对B-Tree进行扫描,需要把整棵树遍历一遍,而B+Tree只需要遍历他的所有叶子节点即可;
3、B+Tree磁盘读写能力更强,因为根节点和支节点不保存数据区,所有根节点和支节点同样大小的情况下,保存的关键字要比B-Tree要多,也就意味着树的高度相对较低,IO的操作更少;
4、B+Tree排序能力更强,叶子节点之间天然具有排序功能;
5、B+Tree查询效率更加稳定,每次查询数据的IO次数一定是相同的;
聚集索引
回到我们的索引上来,我们平时在建表的时候都会为其加上主键,有的数据库中如果不指定主键是无法建表的。但是事实上一个加了主键的表并向我们认知中的「表」,而一个没加主键的表,它的数据无序的放置在磁盘存储器上,一行一行的排列的很整齐, 跟我认知中的「表」很接近。如果给表上了主键,那么表在磁盘上的存储结构就由整齐排列的结构转变成了树状结构,也就是上面说的「平衡树」结构,换句话说,就是整个表就变成了一个索引,也就是所谓的「聚集索引」。(这也是为什么一个表只能有一个「聚集索引」,因为主键的作用就是把「表」的数据格式转换成「索引(平衡树)」的格式放置)
因为整张数据表就是平衡树,所以利用其特性,极大的优化数据查询效率。但是凡事都有两面性索引虽然为查询效率带来的提升,但是却严重影响数据修改的效率。因为每次数据的修改都会破坏树结构,为了确保平衡树的结构维持在正确的状态,每次修改操作后都需要重新梳理树结构,这就为系统性能上造成不小的开销,InnoDB存储引擎就是使用了聚合索引。
非聚集索引
非聚集索引,也就是我们平时经常提起和使用的常规索引,非聚集索引和聚集索引一样,同样是采用平衡树作为索引的数据结构。通俗的来讲非聚集索引数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。如果给表中多个字段加上索引,那么就会出现多个独立的索引结构,每个索引(非聚集索引)互相之间不存在关联。每次给字段建一个新索引,字段中的数据就会被复制一份出来, 用于生成索引。 因此给表添加索引会增加表的体积, 占用磁盘存储空间,非聚集索引和聚集索引的区别在于, 通过聚集索引可以查到需要查找的数据, 而通过非聚集索引可以查到记录对应的磁盘地址, 再磁盘地址找到需要的数据。
以上是关于聚集索引和非聚集索引的主要内容,如果未能解决你的问题,请参考以下文章