在MySQL中,索引是在存储引擎层而不是服务器层实现的。所以,并没有统一的索引标准:不同存储引擎的索引的工作方式并不一样,也不是所有的存储引擎都支持所有类型的索引。即使多个存储引擎支持同一种类型的索引,期底层的实现也可能不同。
一、B-Tree索引
当人们讨论索引的时候,如果没有特别指明类型,那多半说的是B-Tree索引,它使用B-Tree数据结构来存储数据。B-Tree通常意味着所有的值都是按照顺序存储的,并且每一个叶子页到根的距离相同,B-Tree对索引列是顺序组织存储的,所以很适合查找范围数据,因为索引树中的节点是有序的,所以索引还可以用于查询中的ORDER BY 操作。
B-Tree索引的限制:
1、如果不是按照索引的最左列开始查找则无法使用索引。
2、不能跳过索引中的列。
3、如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找。
二、哈希索引
哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是一个较小的值,并且不同键值的行计算出来的哈希码也不一样。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。
在MySQL中,只有Memory引起显示支持哈希索引。这也是Memory引擎表的默认索引类型。Memory引擎是支持非唯一哈希索引的,如果多个列的哈希值相同,索引会以链表的方式存放多个记录指针到同一个哈希条目中。因为索引自身只需要存储对应的哈希值,所以索引的结构十分紧凑,这也让哈希索引查找的速度特别快。
哈希索引的限制:
1、哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。不过,访问内存中的行的速度很快,所以大部分情况下这一点对性能的影响并不明显。
2、哈希索引数据并不是按照索引值顺序存储的,所以也就无法用于排序。
3、哈希索引不支持部分索引列匹配查找,因为哈西索引始终是使用索引列的全部内容来计算哈希值的。
4、哈希索引只支持等值比较查询,包括=、IN()、<=>。不支持任何范围查询。
5、访问哈希索引的数据非常快,除非有很多哈希冲突,这样索引维护操作的代价也很高。
因为这些限制,哈希索引只适用用某些特定的场合。而一旦适合哈希索引,则它带来的性能提升将非常显著。
InnoDB引擎有一个特殊功能叫做“自适应哈希索引(adaptive hash index)”。当InnoDB注意到某些索引值被使用得非常频繁时,它会在内容中基于B-Tree索引之上再创建一个哈希索引,这样就让B-Tree索引也具有哈希索引的一些优点。这是一个完全自动的、内部的行为,用户无法控制或者配置,不过如果有必要,完全可以关闭该功能。
如果存储引擎不支持哈希索引,则可以模拟像InnoDB一样创建哈希索引,这可以享受一些哈希索引的便利,例如只需要很小的索引就可以为超长的键创建索引。
三、空间数据索引(R-Tree)
MyISAM表支持空间索引,可以用作地理数据存储。和B-Tree索引不同,这类索引无须前缀查询。空间索引会从所有维度来索引数据。查询时,可以有效地使用任意维度来组合查询。必须使用MySQL的GIS相关的函数如MBRCONTAINS()等来维护数据。MySQL的GIS支持并不完善,所以大部分人都不会使用这个特性。开源关系数据库系统中对GIS的解决方案做得比较好的是PostgreSQL的PostGIS。
四、全文索引
全文索引是一种特殊类型的索引,它查找的是文本中的关键词,而不是直接比较索引的值。全文索引和其他几类索引的匹配方式完全不一样。它有许多需要注意的细节,如停用词、词干和复数、布尔搜索等。全文索引更类似于搜索引擎做的事情,而不是简单的WHERE条件匹配。
在相同的列上同时创建全文索引和基于值的B-Tree索引不会有冲突,全文索引适用于MATCH AGAINST操作,而不是普通的WHERE条件操作。
希望我的分享对你有帮助。欢迎关注我的微信公众号:javaSharing。