这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
MySQL的索引是在存储引擎层实现,和服务器层无关,因此没有统一的索引标准,不同的存储引擎支持不同类型的索引,对同类型索引的底层实现和支持方式也不同。
B树索引
大多数的MySQL引擎都支持B树索引,不同的存储引擎有所差异。以MyISAM和InnoDB对比,在存储内容上,MyISAM使用了前缀压缩技术使得索引更小,InnoDB按照原数据格式进行存储;在行内容的执行上,MyISAM存储“行的物理位置”,InnoDB存储对应“行的主键”。
B树索引使用的数据结构为B+树,其所有内容都存储在叶子节点上,并且叶子节点间有双向指针进行连接,当我们对数据表的A、B、C列建立一个联合索引index(A,B,C),对以下类型的查询有效
- 全值匹配:即
where A='a' and B=2 and C='c'
- 匹配最左前缀:即
where A='a'
- 匹配列前缀:即
where A like 'a%'
- 匹配范围值:即
where A between 'a' and 'd'
- 精确匹配某一列并范围匹配另外一列:即
where A = 'a' and b between 1 and 10
- 仅访问索引的查询:即
select A
- 使用索引列的排序:即
ORDER BY A, B
对于以下场景无法使用索引 - 不是从索引最左列开始匹配:即
where B=2
- 跳过了索引列:即
where A='a' and C = 'c'
- 某列使用范围查询,后面的列无法使用索引:即
where A between 'a' and 'c' and B = 1
哈希索引
哈希索引是使用哈希表作为数据结构,只在精确匹配才有效。在MySQL中只有Memory引擎使用了哈希索引,索引自身只需存储对应的Hash值,因此结构紧凑并且速度快。
由于是用字段值的哈希值进行精确匹配,因此使用哈希索引的如下的限制
- 只包含Hash值和指针,不存储字段值,因此不能使用索引值来避免读取行
- 不按照索引值顺序存储,无法排序
- 不支持部分索引列匹配查找,因为是按照全部内容来计算哈希值
- 不支持范围查询
- Hash冲突很多的情况下维护索引的代价高
如何自定义哈希索引
InnoDB提供了“自适应哈希索引”,在当某些索引值被使用的非常频繁时,会在内存中创建一个哈希索引进行快速查找,但这个无法由用户进行配置,我们可以自行创建哈希索引,如下所示创建一个存储url
列哈希值的crc_url
列
alter table table_name
add url_crc int default crc32(url) not null;