MySQL的B树索引和哈希索引

271 阅读3分钟

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

MySQL的索引是在存储引擎层实现,和服务器层无关,因此没有统一的索引标准,不同的存储引擎支持不同类型的索引,对同类型索引的底层实现和支持方式也不同。

B树索引

大多数的MySQL引擎都支持B树索引,不同的存储引擎有所差异。以MyISAM和InnoDB对比,在存储内容上,MyISAM使用了前缀压缩技术使得索引更小,InnoDB按照原数据格式进行存储;在行内容的执行上,MyISAM存储“行的物理位置”,InnoDB存储对应“行的主键”。

B树索引使用的数据结构为B+树,其所有内容都存储在叶子节点上,并且叶子节点间有双向指针进行连接,当我们对数据表的A、B、C列建立一个联合索引index(A,B,C),对以下类型的查询有效

  1. 全值匹配:即where A='a' and B=2 and C='c'
  2. 匹配最左前缀:即where A='a'
  3. 匹配列前缀:即where A like 'a%'
  4. 匹配范围值:即where A between 'a' and 'd'
  5. 精确匹配某一列并范围匹配另外一列:即where A = 'a' and b between 1 and 10
  6. 仅访问索引的查询:即select A
  7. 使用索引列的排序:即ORDER BY A, B 对于以下场景无法使用索引
  8. 不是从索引最左列开始匹配:即where B=2
  9. 跳过了索引列:即where A='a' and C = 'c'
  10. 某列使用范围查询,后面的列无法使用索引:即where A between 'a' and 'c' and B = 1

哈希索引

哈希索引是使用哈希表作为数据结构,只在精确匹配才有效。在MySQL中只有Memory引擎使用了哈希索引,索引自身只需存储对应的Hash值,因此结构紧凑并且速度快。

由于是用字段值的哈希值进行精确匹配,因此使用哈希索引的如下的限制

  1. 只包含Hash值和指针,不存储字段值,因此不能使用索引值来避免读取行
  2. 不按照索引值顺序存储,无法排序
  3. 不支持部分索引列匹配查找,因为是按照全部内容来计算哈希值
  4. 不支持范围查询
  5. Hash冲突很多的情况下维护索引的代价高

如何自定义哈希索引

InnoDB提供了“自适应哈希索引”,在当某些索引值被使用的非常频繁时,会在内存中创建一个哈希索引进行快速查找,但这个无法由用户进行配置,我们可以自行创建哈希索引,如下所示创建一个存储url列哈希值的crc_url

alter table table_name
   add url_crc int default crc32(url) not null;