【问题标题】:MySQL InnoDB table with a Hash Index带有哈希索引的 MySQL InnoDB 表
【发布时间】:2017-12-03 09:23:42
【问题描述】:

我有一张这样的桌子。

ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

后来我创建了一个这样的 HASH 索引。

CREATE INDEX index ON table (column) USING HASH;

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

喜欢

explain Select * from table where column=132;

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

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

【问题讨论】:

    标签: mysql indexing hash


    【解决方案1】:

    InnoDB 默默地将“HASH”更改为“BTree”。 BTree 索引的功能与 HASH 的功能相同,此外还有更多功能。或者你认为有什么好的理由需要 Hash?

    “很好的理由”——MySQL 是多年前创建的。它的设计初衷是“精益求精”。许多特性被归结为“一刀切”:用于索引的 BTree; JOINing 等的嵌套循环连接

    同时,为了将来的扩展和伪兼容性,包括了一些常见的语法变体——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 数据类型和函数
    • FULLTEXTSPATIAL InnoDB (5.7, 8.0) 中的索引(因此可以弃用 MyISAM)
    • DESC in INDEXes (8.0)(非常很少用例真正需要这个)
    • “窗口化”函数(MariaDB 10.2,然后是 MySQL 8.0)
    • CTE(MariaDB 10.2,然后是 MySQL 8.0)
    • 安全性:更好的密码处理(4.1?、5.6、8.0)
    • HA(高可用性)(带有 Galera 的 MariaDB;带有 InnoDB Cluster 的 8.0)
    • 静态加密 (8.0?)

    请注意列表是如何从“必须拥有”到“很高兴拥有”的顺序排列的。未来可能包括

    • 多线程执行(无论如何,如果您受 I/O 限制,则无用)
    • HASH 索引(和其他类型)
    • 全局UNIQUEFOREIGN KEY 用于PARTITIONing。 (并不是说分区很有用。)
    • 与标准和其他供应商的语法兼容性更高(MariaDB 在这方面做得更好)

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

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

    【讨论】:

    • 好吧,哈希是关于没有任何排序的特定键,因此插入不会强制系统重新排序 btree。如果我总是知道自己想要什么,并且我的主要操作是“给出 id xyz 的东西”,那么哈希索引应该具有 O(1) 与 O(log n)。哈希索引不是为范围操作而构建的,所以缺点仍然存在,有很多充分的理由希望在 btree 上进行哈希,否则。
    • @shadowdroid - BTrees 有时需要处理块;哈希有时需要建立一个“链”。对于 十亿 行,O(log n) 约为 5。
    • 感谢您指出这一点。它不会改变有时哈希索引是一个完全有效的选择的事实。尤其是如果我没有范围,例如,如果我将加密数据存储为某些链接的密钥,那么一次性链接 BTREE 有点没用。仍然在大多数情况下,在 SQL 中,我们希望选择范围,因此对我来说 BTREE 是大多数应用程序的更好选择。我去是为了“好理由”。可能有充分的理由,这就是我想说的。
    • @shadowdroid - 我在答案中添加了详细说明“充分理由”。
    【解决方案2】:

    InnoDB中的特性叫做自适应哈希索引

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

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

    【讨论】:

    • 是的。该功能在内部使用如果它被认为有用并且数据将适合内存中的哈希。也就是说,它的大小是有限的,而常规索引的大小实际上是无限的。
    • slave_rows_search_algorithms 可以包含HASH_SCAN,但我对此一无所知。
    猜你喜欢
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    • 2014-01-29
    • 2017-03-26
    • 2012-11-10
    • 2020-08-23
    相关资源
    最近更新 更多