首先我们知道,MySQL的索引分为BTree索引和 哈希索引,而BTree索引又比较常见,那么我们要先了解BTree索引的底层,B+树,不太清楚的可以看看这篇文章。
为什么要用B+树?
红黑树被广泛应用于java和C++的一些数据结构的底层结构,但是即便这么常用的一个数据结构,为什么在MySQL中不用来作为索引,而选择B+树呢?
这个问题其实可以拓展成,B树,红黑树,B+树都是被称作效率很高的数据结构,为什么在数据库我们要选择B+树?
首先我们要知道,数据库是用来存取数据的,那么存取的这个过程肯定是最主要的目标,怎么让存取更高效是数据库的一个重点,所以从这个方面我们来看。
红黑树其实是不标准的平衡二叉树,他更可以说是为了减少平衡二叉书的左旋右旋操作(因为比较耗费时间)次数而特殊定制的数据结构,所以本质上还是二个二叉树。
而相对而言,B树和B+树可以算是多叉树,在这个方面,B树和B+树在相同情况下会比红黑树更矮更胖。
从基础的数据结构我们能知道树越矮越胖,那么从树上取数据的次数就会更少(因为找数据的时候,树每一层一般情况下只取一个节点,所以IO次数可以看成跟树的深度成正比)
B树和B+树的区别就是B树每个节点都是用来存数据,而B+树节点只存索引,在IO的内存大小统一的情况下,从B+树中一次能取出的节点肯定会比B树多,这样一来,可以进一步的减少IO的次数,所以B+树是MySQL的最佳选择。
MySQL的两种存储索引MyISAM与InnoDB
在MySQL中有两种存储索引,MyISAM和InnoDB,底层虽然都是B+Tree但是在具体的方法上还是有所不同,MyISAM的方法被称为非聚簇索引,InnoDB是聚簇索引。聚簇索引和非聚簇索引其实很好理解。
聚簇索引就是把数据全放在一起,存放在索引上,这样在遍历索引树的时候,只要找到对应的叶子节点就可以直接找到想要的数据
非聚簇索引就是把数据分开存放,看上去数据好像是整个存放在内存或者磁盘中(虚拟地址),但这些数据可能分布在不同的地址,非聚簇索引的叶子结点存放相对应数据的地址,因为数据都分散存放,所以拿到地址后要去相对应的地方取数据。
InnoDB聚簇索引
在InnoDB中,系统为每张表依据主键建立一颗B+树,将数据直接存放在叶子结点上,如果没有定义主键,innodb会选择非空的唯一索引代替。如果没有这样的索引,innodb会隐式的定义一个主键来作为聚簇索引。
如果是直接用行或者id作为主键来建立比如通过"where id = 14"这样的条件查找主键,那么只需要根据B+树的检索算法即可查找到对应的叶节点,然后获得行数据,这样的话就只需要一颗B+树。
如果对Name或者某个列作为主键进行索引,那么就需要有一个辅助结构,先找到该取值对应的行,再在另外一个辅助B+树上进行检索,读取行数据,这样的话就需要一个添加一颗辅助键索引的B+树。
MyISAM非聚簇索引
非聚簇索引的B+树结构基本和聚簇索引一致,只是非聚簇索引的数据是单独存储的,所以在叶子结点只存了定位数据的指针。
MyISAM与InnoDB,聚簇索引和非聚簇索引的区别
首先我们要知道,MySQL从5.5版本开始,默认的索引已经改成InnoDB了,之前是MyISAM,所以一定程度上我们可以知道,官方已经认为在一定程度上,InnoDB不说比MyISAM更完美,但最少在大多数场景下,比MyISAM是更优的选择。
- InooDB支持事务,MyISAM不支持事务,在NoSQL越来越受欢迎的现在,MySQL等关系型数据库的支持事务的功能就显得尤为重要,所以在需要保证事务的ACID特性的情景上,MyISAM明显是不适合的
- InnoDB支持外键,而MyISAM是不支持外键的,外键更多的是保证数据的参照完整性,一张表的主键在另外一张表中作为一列,那么这一列就是第二张表的外键。
- InnoDB支持行级锁,而MyISAM只支持表锁,那么对于需要颗粒度更小的锁操作,明显MyISAM是达不到效果的
- 在系统崩溃后,MyISAM恢复起来更加困难,InnoDB相对简单。
虽然InnoDB在很多方面比MyISAM更优,更适用,但有些情况MyISAM还是比InnoDB更优的
- 因为InnoDB支持事务,所以在不同的事务中数据的总行数会不一样,对于select count(*) from table,InnoDB需要去扫描全表返回结果,而MyISAM用一个变量直接保存了这个值(不能用任何where条件),在这种情况下MyISAM是直接返回结果的
- InnoDB在5.7版本之后才支持全文索引,全文索引和like %不一样,全文索引更形象的其实是搜索引擎,全文索引的效率比like 快太多了,他所用的数据结构是倒排索引,现在只能为CHAR、VARCHAR、TEXT列创建。在5.7之前的版本如果需要建立全文索引只能用MyISAM
InnoDB在刚出来的时候被指出读能力没有MyISAM好,并且高并发能力也没有MyISAM好,在经过多年的优化之后,InnoDB的读能力有显著的提高,并且也通过MVCC实现了高并发的处理,之前因为支持事务所造成的一些不足,也基本被优化了。
而由于MyISAM的不稳定,有时候会崩溃,并且恢复并不容易,加上不支持行锁,事务,外键等很多规范系统所需要的功能,已经基本被淘汰了,很多说MyISAM优于InnoDB的,基本时间停留在很多年前了。