MySQL InnoDB&MyISAM 支持Hash么

MySQL InnoDB&MyISAM 支持Hash么

我们在使用MySQL的时候,关于索引的数据类型,使用的最多的就是HASH和BTREE. 很多开发人员很有经验的会在创建某些字段的索引的时候告诉MySQL的存储引擎:使用HASH !. 我一段时间也是这样胸有成竹的按照这个理论选择索引类型的: 如果是精确的equals比较查询,那么就使用HASH,如果使用范围查询和大小比较查询那么最好使用BTREE.

由于以前的开发经历就是功能开发为主,对具体的细节不是很在意,一般MySQL也能满足需求,所以我天真的以为既然建表语句可以指定HASH而且没有报警告和错误,那么这个索引的底层数据结构肯定是HASH,然后我就放心的使用equals精确查询数据了.直到有一天我看到MySQL的官方文档,才对这个产生深刻的反思.

原文如下:

Most MySQL indexes (PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT) are stored in B-trees. Exceptions: Indexes on spatial data types use R-trees; MEMORY tables also support hash indexes; InnoDB uses inverted lists for FULLTEXT indexes.

什么? 绝大多少MySQL index是BTREE?除了空间位置数据使用了RTREE以及MEMORY TABLE以及使用倒排列表的FULLTEXT indexes?

InnoDB 官方解读

然后我马上检查了InnoDB的文档:

InnoDB Storage Engine Features

发现InnoDB其实是不支持HASH索引的,但是它可以使用称为Adaptive Hash的技术来在表象上支持HASH. 这也就是我为什么以前使用InnoDB引擎并指定index类型为HASH的来建表并执行SQL的时候,功能依然看起来正常的本质原因.

MyISAM 官方解读

我继续检查了MyISAM的文档:
MyISAM Storage Engine Features

那么很遗憾,MyISAM也是不支持Hash的.而且MyISAM也不支持类似InnoDB的Adaptive Hash的技术来在表象上支持HASH.

所以我们得出结论:

  • MyISAM和InnoDB 不支持HASH
  • InnoDB可以使用Adaptive Hash来间接支持HASH
  • MEMOEY才能同时支持HASH和BTREE

我们在建表时给某些字段添加hash索引,或者后期为某表添加hash索引时,如果他们的存储引擎为InnoDB或MyISAM,则sql脚本本身是不会报错的,但是我们会发现,该hash索引字段的index_type仍然为BTREE.这其实是MySQL为了照顾使用习惯而做到一些特殊处理,其实底层会忽略你指定索引为HASH的逻辑,依然使用BTREE

实际验证

本次我使用MySQL8作为测试环境,通过实际的代码操作做实际的论证.

InnDB验证

CREATE TABLE index_type_test (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(32) NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `name_UNIQUE` using hash(name)
) ENGINE = InnoDB;

然后我们查询这个表的索引类型:

mysql> show index from index_type_test;

InnoDB index type
所以实际测试表明InnoDB会忽略你指定的HASH类型,依然使用BTREE

有关自适应HASH的内容请看: MySQL InnoDB中的Adaptive Hash

MyISAM验证

CREATE TABLE index_type_test (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(32) NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `name_UNIQUE` using hash(name)
) ENGINE = MyISAM;

然后我们查询这个表的索引类型:
MyISAM index type
所以实际测试表明MyISAM会忽略你指定的HASH类型,依然使用BTREE.

本文原创链接:

参考链接:

你可能感兴趣的:(mysql)