高性能/索引类型 哈希索引以及其他索引

本文深入探讨了数据库索引的三种类型:哈希索引、空间数据索引(R-Tree)和全文索引。哈希索引在特定场景下能提供快速查找,但不支持范围查询和排序;空间数据索引在地理数据存储中应用,而全文索引则用于文本搜索。不同数据库引擎支持不同的索引类型,理解这些特性有助于优化查询性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 哈希索引

1.1 哈希索引介绍

⏰ 哈希索引介绍
  1. 哈希索引( hash index ):基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码( hash code )。哈希码是一个较小的值,并且不同键值的行计算出来的哈希码也不一样。
  2. 哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。
  3. 哈希索引优点:索引自身只需存储对应的哈希值,所以索引的结构十分紧凑,所以哈希索引查找的速度非常快。虽然哈希索引只能适用于某些特定的场合。但是当查询适合哈希索引,则它带来的性能提升将非常显著。
⏰ 引擎对哈希索引的支持
  1. Memory引擎:在MySQL中,只有 Memory引擎显式支持哈希索引。这也是 Memory 引擎表的默认索引类型,Memory 引擎同时也支持 B-Tree 索引。

Memory:Memory 引擎是支持非唯一哈希索引的,这个特性在数据库世界中是与众不同的。如果多个列的哈希值相同,索引会以链表的方式存放多个记录指针到同一个哈希条目中。

  1. InnoDB引擎:在InnoDB引擎中对哈希索引的支持叫做 “自适应哈希索引(adaptive hash index)🌖”。当 InnoDB 注意到某些索引值被使用的非常频繁时,它会在内存中基于 B-Tree 索引之上再创建一个哈希索引,这样就让 B-Tree 索引也具有哈希索引的一些优点,比如快速的哈希查找。

这是一个完全自动的,内部的行为,用户无法控制或者配置,不过如果有必要,完全可以关闭该功能。

⏰ 哈希索引原理
  1. 表范例:假设我们有如下表和数据:
🍈
CREATE TABLE testhash(
	fname VARCHAR(50) NOT NULL,
	lname VARCHAR(50) NOT NULL,
	KEY USING HASH(fname)
) ENGINE=MEMORY
🍈
mysql> SELECT * FROM testhash;
+-------+-----------+
| fname | lname     |
+-------+-----------+
| Arjen | Lentz     |
| Baron | Schwartz  |
| Peter | Zaitsev   |
| Vadim | Tkachenko |
+-------+-----------+
  1. 假设索引使用假想的哈希函数 f() ,它返回下面的值(都是示例数据,非真实数据):
🍈
f('Arjen')=2323
f('Baron')=7437
f('Peter')=8784
f('Vadim')=2458
  1. 则哈希索引的数据结构如下:
🍈
+-------+-----------+
|(Slot) |(Value)  |
+-------+-----------+
| 2323 | 指向第1行的指针 |
| 2458 | 指向第4行的指针 |
| 7437 | 指向第2行的指针 |
| 8784 | 指向第3行的指针 |
+-------+-----------+
  1. 上述每个槽中的哈希值都是有顺序的,但是数据不是行。现在我们解析,如下查询:
🍈
mysql> SELECT lname FROM testhash WHERE fname='Peter';
+---------+
| lname   |
+---------+
| Zaitsev |
+---------+

查询过程:MySQL 先计算 Peter 的哈希值,并使用该值寻找对应的记录指针。因为 f(‘Peter’)=8784,所以 MySQL 在索引中查找 8784,可以找到指向第3行的指针,最后一步是比较第三行的值是否为 Peter ,以确保就是要查找的行。
6. 索引自身只需存储对应的哈希值,所以索引的结构十分紧凑,所以哈希索引查找的速度非常快。

⏰ 哈希索引限制
  1. 哈希索引只包含哈希值和行指针,而不存储字段值,所以哈希索引不能使用索引中的值来避免读取行。不过,访问内存中行的速度很快,所以大部分情况这一点对性能的影响并不明显。
  2. 哈希索引数据并不是按照索引值排序存储的,所以也就💯无法用于排序
  3. 哈希索引也💯不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容来计算哈希值的。例如,在数据列(A,B)上建立哈希索引,如果查询只有数据列A,则无法使用该索引。
  4. 哈希索引只支持等值比较查询,包括=IN()<=>。同样的也不支持任何范围查询,例如 WHERE price > 100。
  5. 访问哈希索引的数据非常快,除非有很多哈希冲突(不同的索引列值却有相同的哈希值)。当出现哈希冲突的时候,存储引擎必须遍历链表中所有的行指针,逐行进行比较,直到找到所有符合条件的行。
  6. 如果哈希冲突很多的话,一些索引维护操作的代价也会很高。例如,如果在某个选择性很低(哈希冲突很多)的列上建立哈希索引,那么当从表中删除一行时,存储引擎需要遍历对应哈希值的链表中的每一行,找到并删除对应行的引用,冲突越多,代价越大。

上述的限制,导致哈希索引只适用于某些特定的场合。但是一旦适合哈希索引,则它带来的性能提升将是非常显著的。

2. 空间数据索引(R-Tree)

⏰ 空间数据索引(R-Tree)
  • 使用 ❗SPATIAL 关键字表示。
  • MyISAM 引擎支持空间索引,可以用于地理数据存储。和 B-Tree 索引不同,这类索引无需前缀查询。空间索引会从所有维度来索引数据。查询时,可以有效地使用任意维度来组合查询。必须使用 MySQL 的 GIS 相关函数 如 MBRCONTAINS() 等来维护数据。MySQL 的 GIS 支持并不完善,所以大部分人都不会使用这个特性。开源数据库对 GIS 的解决方案做得比较好的是 PostgreSQL 和 PostGIS。

3. 全文索引

⏰ 全文索引
  • 使用 ❗FULLTEXT 关键字表示。
  • 全文索引是一种特殊类型的索引,它查找的是文本中的关键词,而不是直接比较索引中的值。全文搜索和其他几类索引的匹配方式完全不一样。它有许多需要注意的细节,如 停用词、词干、和复数、布尔搜索等。全文索引更类似于搜索引擎做的事情,而不是 WHERE 条件匹配。
  • 在相同的列上同时创建全文索引和基于值的 B-Tree 索引不会有冲突,全文索引适用于 MATCH AGAINST 操作,而不是普通的 WHERE 条件操作。

4. 其他索引

⏰ 其他索引
  • 还有很多的第三方的索引引擎使用不同类型的数据结构来存储索引。例如 TokuDB 使用分形树索引( fractal tree index),这是一类较新开发的数据结构,既有 B-Tree 的很多优点,也避免了 B-Tree 的一些缺点。
  • InnoDB 的特性,包括聚簇索引,覆盖索引等。多数情况下,InnoDB的特性也适用于 TokuDB。
  • ScaleDB 使用 Patricia tries,其他一些存储引擎技术如 InfiniDB和 Infobright 则使用了一些特殊的数据结构来优化某些特殊的查询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值