开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
索引
从本节开始将对数据库进行介绍,会给各位介绍数据库的索引,事务,锁以及日志等。由于内容较多,因此会分成几节进行介绍。索引是帮助MySQL高效获取数据的排好序的数据结构,本节将从数据库索引开始,介绍索引的分类,数据结构及作用。
B+树索引
如果我们需要一个数据结构去排列有序的数据,首先想到的应该是二叉排序树,所有小于该值的在左边,大于该值的在右边,但是这可能会导致某一边高度过大,为了优化,我们有红黑树,它可以帮助我们平衡高度。但是这也并不是作为数据库索引数据结构最理想的方法。
我们知道数据库存储在磁盘上,如果使用红黑树意味着我们变换一个节点就需要做一次磁盘IO,这样效率是很低的,因此我们需要减少磁盘IO的次数,那么需要从两个方面去改进,一个是增加节点大小,另一个则是降低树的整体大小,由此,B树呼之欲出。
如图在B树中,一个节点包含了多个数据,为了减少磁盘IO的次数,这一个节点就是一个磁盘页,也就是说一次磁盘IO可以读到多个数据的值。但是实际上MySQL底层也没有选择B树作为索引数据结构,而是对B树进行进一步的改良,也就是B+树。
B+树和B树不同的是,B+树的非叶子结点只存放索引值,不存放数据,只在叶子结点存放实际数据,也就是说叶子结点包含了所有的索引。那么上面的那些结点算是冗余结点,B+树的大小会比B树更大,就是因为这些冗余结点,那么为什么要设计这些冗余结点呢?
原因还是因为磁盘IO的优势,在MySQL中,一个磁盘页划分大概是16K。如果这个16K像B树一样放索引和数据的话,那么这一个磁盘页能放下的索引就少了,会导致树高增加。而如果像B+树一样只放索引的话,能够放的索引就多了。如果一个索引是bigint占8B,一个指针占6B,那么这一个16KB的磁盘页就可以放将近1200个索引。假设一行数据占1K的话一个叶子结点磁盘页就可以放16个数据,那么一个高度为3的B+树就可以放1200*1200*16条2000多万的数据。
另外一个区别是B+树的叶子结点每一个结点间有一个指针相连,这是为了提高执行范围查找的效率。
Hash索引
Hash索引是对索引的Key进行一次Hash运算定位出数据存储的位置。
Hash索引很多时候可能比B+树索引更加高效,因为只需要对主键进行Hash后就可以很快找到对应的结点,而B+树还需要去进行多次的磁盘IO。但是在大部分情况下还是选择B+树索引,因为Hash索引它仅能满足‘=’或者‘in'的查询,并不支持范围查找。如果是范围查找会退化为全表扫描,这是不可接受的。
InnoDB与MySIAM
在MySQL中,不同的引擎索引结构也是不一样的。MySIAM是一种非聚集索引的存储引擎,而InnoDB是一种聚集索引的存储引擎,它们都是针对表的,也就是说不同的表可以有不同的存储引擎。
在MySIAM中,有三种文件,frm,MYD和MYI。frm是MySIAM和InnoDB都有的一种文件,是表结构文件,而MYD和MYI从最后一个字母可以看出来一个是Data数据一个是Index索引。也就是说MySIAM引擎中,索引和数据是分开的。当一个请求在查询时,会现在MYI中遍历B+树,到了叶子结点存储的是该数据在MYD中的磁盘索引号,最后从MYD中拿到数据。
而InnoDB中,只有两种文件,frm和ibd。InnoDB的主键索引和数据在同一个文件中。InnoDB的主键索引树的叶子结点保存的是具体数据。如果有二级索引的话,二级索引树的叶子结点保存的是主键值,需要拿到主键值后再到主索引进行回表查询。在InnoDB中推荐使用整形的自增主键,因为自增主键可以避免B+树索引的变形。
最左前缀原理
有的时候我们不会以一个值作为主键,我们可能会创建联合索引。
当我们创建联合索引后,索引树会根据从左到右的顺序去进行排序,如上图会先根据name去进行排序,再根据后面的。因此,最左前缀就是我们在查询时的条件应该是左前缀,如果跳过某一个的字段,那么这个索引树其实是无序的,就没办法再走索引树。
总结
本节介绍了数据库的索引,包括B+树索引和Hash索引。同时也分析了InnoDB和MySIAM的异同。最后解释了最左前缀原理。希望我的介绍能给你带来对数据库更清楚的认识。
感谢观看!