**深入理解MySQL索引原理**
熊大
说索引之前我们先谈下mysql 这个渣男。
它支持诸多存储引擎,各存储引擎对索引的支持也各不相同,因此MySQL支持多种索引类型,如BTree索引,二叉树索引,哈希索引,有序数组、全文索引等等。
现实工作中如果一个sql比较慢分析一番说加一个索引吧。一般这个sql就会飞起那么在这其中索引起什么作用呢?
有人说索引就像一本书的目录如果一本书1000页,如果想找到某个具体的内容最简单方法就是查看目录然后翻到该页即可。
常见的索引类型:
哈希索引
哈希思路很简单,把值放在数组里,用一个哈希函数把
key 换算成一个确定位置,然后把 value 放在数组的这个位置。
当然我们知道哈希过程中算出的值可能是一样的那就拉出一个链表来记录即可。
假如有一本恋爱宝典里面记录了各种恋爱秘籍那么对呀hash如下图
那么其实可以看到如果是等值查询的情况我们很容易就把值查询出来 但是如果范围查询这个就比较尴尬了。
等值查询这种情况一般noSql运用较多
备注:上面的数据结构和hashmap是否一致呢?那么一道经典面试题map、list如何选择
面对范围查询于是有序数组应运而生。那么存储结构如下
那么可以看出这个简直就是为范围查找量身制作的。但是如果更新数据代价有点大后续数据会挨个挪动。
二叉搜索树也是经典的数据结构:
二叉树的特点
就是左节点要比父节点小、右节点比父节点大。如果要查章节4那么他会一次从1–>2—>4
理论来讲二叉搜索树是查找最快的因为他的时间复杂度O(log(N))
当然前提是要维持这个二叉树的平衡。
全文索引
通过建立倒排索引,可以极大的提升检索效率,解决判断字段是否包含的问题。
那么我们经常使用的mysql innodb引擎是怎么存储数据的呢
我们都知道它采用的是btree模型假如我们有一个表如下:
innodb使用了 B+ 树索引模型,所以数据都是存储在 B+ 树中的。
create table test(
id int primary key,
k int not null,
name varchar(16),index (k))engine=InnoDB;
存储数据如下图:
由上图可以看出主键直接对应的是该行内容。而普通索引对应的是相应的主键。
也就是说普通索引如果查找相应数据需要先找到对应主键然后根据主键在找到相应的数据。
这就是我们所说的回表。当然只查这个索引对应的内容是不需要回表的。
select * from test where id=10;
select k from test where k=300;
这两个语句是不用回表的。第一个sql是因为根据主键查询 第二个虽然根据普通索引查询但是只是查询了改字段所以也不需要回表。
索引的维护:
我们知道innodb的存储结构是b+tree
每一个索引就是一颗b+tree 而其中每个叶子节点则是数据页(page) 数据页里面是由一行行的数据组成的。
那么对这个数据页我们则是希望它能够写满再去申请下一页自增主键则满足这个要求。当然在实际使用情况中页可能裂开或者合并。
小知识点
假设mysql 引擎是innodb没有主键它是怎么做的?
如果没有主键innodb会给默认创建一个Rowid做主键
主键如何选择:
业务允许的情况下最好选择自增主键
1、自增主键可以更充分的使用数据页。
2、普通索引的空间占用也比较小
参考: