带有哈希索引的 MySQL InnoDB 表

chi*_*tiz 4 mysql indexing hash

我有一张这样的桌子。

ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Run Code Online (Sandbox Code Playgroud)

后来我创建了一个像这样的哈希索引。

CREATE INDEX index ON table (column) USING HASH;
Run Code Online (Sandbox Code Playgroud)

后来我尝试了一些解释查询。

喜欢

explain Select * from table where column=132;
Run Code Online (Sandbox Code Playgroud)

我看到引擎正在使用 possible_keys 上的索引,并且在关键内容中显示了索引的名称!

但在文档中说 InnoDB 不允许哈希索引现在我想知道为什么我的 innoDB 据说允许哈希索引?

Ric*_*mes 6

InnoDB默默地将“HASH”更改为“BTree”。BTree 索引的作用与 HASH 的作用相同,甚至更多。或者你认为有什么充分的理由需要哈希?

“充分的理由”——MySQL 是在很多年前创建的。它被设计为“精简而简朴”。许多功能都归结为“一刀切”:BTree 用于索引;嵌套循环连接 forJOINing

同时,为了未来的扩展和伪兼容性,包括了一些常见的语法变体——HASH用于索引、DESC索引排序等。即使这些“谎言”会发生什么,数据库引擎仍然会给你“正确”的答案。

随着时间的推移,最明显的捷径已经得到纠正。

  • 复制(3.xx?)
  • 事务(在 4.0 中添加 InnoDB)(MyISAM 有LOCK TABLES,但这还不够。)
  • information_schema(4.1?)(相对于各种SHOW命令)注:8.0用“数据字典”对其进行了彻底修改)
  • 字符集和排序规则 (4.1)(与“latin_swedish_ci”相比,这对于实现者来说已经足够好了。)
  • 存储例程(与客户端代码相比)(5.0)
  • 子查询(TEMPORARY TABLEs不够)
  • 各种JOIN优化(5.6、5,7、8.0)
  • only_full_group_by(MariaDB 10.1?,5.7)
  • ALTER不“总是”复制表格(主要是 5.7)
  • “生成”列 (5.7)
  • “表空间”(5.7)
  • JSON 数据类型和函数
  • FULLTEXTSPATIALInnoDB 中的索引(5.7、8.0)(因此 MyISAM 可以被弃用)
  • DESCINDEXes(8.0)中(很少有用例真正需要这个)
  • “窗口化”函数(MariaDB 10.2,然后是 MySQL 8.0)
  • CTE(MariaDB 10.2,然后是 MySQL 8.0)
  • 安全性:更好的密码处理(4.1?、5.6、8.0)
  • HA(高可用性)(MariaDB 与 Galera;8.0 与 InnoDB Cluster)
  • 静态加密(8.0?)

请注意该列表是如何从“必须有”到“最好有”排序的。未来可能包括

  • 多线程执行(如果你是 I/O 绑定的话就没用)(8.0 中的极少数用例)
  • HASH索引(和其他类型)(MariaDB 10.4,仅适用于UNIQUEon TEXT/BLOB
  • 全球UNIQUEFOREIGN KEYPARTITIONing. (并不是说分区非常有用。)
  • 与标准和其他供应商的更多语法兼容性(MariaDB 在这方面已经做得更好了)

与此同时,有些东西正在消失(或者已经消失——无论是在 MariaDB 还是 MySQL 中)

  • 为多种计算机进行编译——例如 Atari
  • 查询缓存——对于基准测试很方便,但在生产环境中并不是很有用。在任何“集群”拓扑中实施都是一个主要麻烦。
  • MyISAM相对于InnoDB有很大的缺陷,并且优点很少。(可以说,唯一的好处是需要更少的磁盘空间。)

  • 哈希是关于特定键的,没有任何排序,因此插入不会强制系统对 btree 重新排序。如果我总是知道我想要什么,并且我的主要操作是“给出 id xyz 的东西”,那么哈希索引应该具有 O(1) vs O(log n)。哈希索引不是为范围操作而构建的,因此缺点仍然存在,有很多充分的理由需要在 btree 上使用哈希,或者以其他方式进行哈希索引。 (5认同)
  • 感谢您指出这一点。它并没有改变这样的事实:有时哈希索引是完全有效的选择。特别是如果我没有范围,例如如果我将加密数据存储为某些链接的密钥,那么一次链接 BTREE 就有点无用了。在大多数情况下,在 SQL 中我们仍然希望选择范围,因此对我来说 BTREE 对于大多数应用程序来说是更好的选择。我去是为了“充分的理由”。可能有充分的理由,这就是我想说的。 (2认同)

小智 5

InnoDB中的特性称为自适应哈希索引

是否使用哈希索引取决于表的规模和查询频率,这完全是内部策略,通常无需配置。

https://dev.mysql.com/doc/refman/5.7/en/innodb-adaptive-hash.html