MySql 最经常使用存储引擎 InnoDB 和 MyISAM 都不支持 Hash 索引,它们默认的索引都是 B-Tree。可是假设你在创建索引的时候定义其类型为 Hash,MySql 并不会报错,并且你通过 SHOW CREATE TABLE 查看该索引也是 Hash,仅仅只是该索引实际上还是 B-Tree。

比方表 data_dict 的 DDL:

CREATE TABLE `data_dict` (
`data_type` varchar(32) NOT NULL COMMENT '数据字典类型',
`data_code` tinyint(4) NOT NULL COMMENT '数据字典代码',
`data_name` varchar(64) NOT NULL COMMENT '数据字典值',
PRIMARY KEY (`data_type`,`data_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='数据字典表';

我们为 data_name 字段建立 Hash 索引:

ALTER TABLE data_dict ADD INDEX data_dict_dn USING HASH (data_name);

打印结果:
受影响的行: 0
时间: 0.345s
然后查看建表 DDL:

SHOW CREATE TABLE data_dict;

打印结果:
CREATE TABLE `data_dict` (
  `data_type` varchar(32) NOT NULL COMMENT '数据字典类型',
  `data_code` tinyint(4) NOT NULL COMMENT '数据字典代码',
  `data_name` varchar(64) NOT NULL COMMENT '数据字典值',
  PRIMARY KEY (`data_type`,`data_code`),
  KEY `data_dict_dn` (`data_name`) USING HASH
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='数据字典表'
是 Hash,所以我们以为创建 Hash 索引成功。
其实并不是如此,我们都被 MySql 给骗了,我们使用 SHOW INDEXES FROM 语句对该表索引进行检索:

SHOW INDEXES FROM data_dict;

打印结果:

打回原形了。只是也不要失望,尽管常见存储引擎并不支持 Hash 索引,但 InnoDB 有还有一种实现方法:自适应哈希索引。InnoDB 存储引擎会监控对表上索引的查找。假设观察到建立哈希索引能够带来速度的提升,则建立哈希索引。
我们能够通过 SHOW ENGINE INNODB STATUS 来查看当前自适应哈希索引的使用状况:
=====================================
2015-07-07 10:51:19 1d68 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 36 seconds
......
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 2633, seg size 2635, 0 merges
merged operations:
 insert 0, delete mark 0, delete 0
discarded operations:
 insert 0, delete mark 0, delete 0
Hash table size 348731, node heap has 2 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
......
从中我们能够看到自适应哈希索引的相关信息:有使用大小、使用情况、每秒使用自适应哈希索引搜索的情况等。

MySql 各种存储引擎的特性对照详单:

从中我们能够看出,

  • InnoDB 支持事务。支持行级别锁定。支持 B-tree、Full-text 等索引。不支持 Hash 索引。
  • MyISAM 不支持事务,支持表级别锁定,支持 B-tree、Full-text 等索引。不支持 Hash 索引;
  • Memory 不支持事务,支持表级别锁定。支持 B-tree、Hash 等索引,不支持 Full-text 索引。
  • NDB 支持事务,支持行级别锁定。支持 Hash 索引。不支持 B-tree、Full-text 等索引;
  • Archive 不支持事务。支持表级别锁定,不支持 B-tree、Hash、Full-text 等索引。

能够使用 SHOW ENGINES 语句查看你的 MySql Server 所支持的存储引擎,比方笔者用于本机測试的 5.6.25-log Win 版的查看结果例如以下:

从中能够看出。InnoDB 是该版本号 MySql 的默认存储引擎。也仅仅有 InnoDB 能够支持事务、行级别锁定、外键。支持的 MEMORY 是基于哈希的,数据都存放于内存。适用于暂时表。没有看到既支持事务又支持哈希索引的 NDB 的身影。

为印证默认的存储引擎,我们创建一个測试表 data_dict_test。注意建表语句里未定义存储引擎:

CREATE TABLE `data_dict_test` (
`data_type` varchar(32) NOT NULL COMMENT '数据字典类型',
`data_code` tinyint(4) NOT NULL COMMENT '数据字典代码',
`data_name` varchar(64) NOT NULL COMMENT '数据字典值',
PRIMARY KEY (`data_type`,`data_code`)
) DEFAULT CHARSET=utf8 COMMENT='数据字典表';

打印结果:

[SQL] CREATE TABLE `data_dict_test` (
  `data_type` varchar(32) NOT NULL COMMENT '数据字典类型',
  `data_code` tinyint(4) NOT NULL COMMENT '数据字典代码',
  `data_name` varchar(64) NOT NULL COMMENT '数据字典值',
  PRIMARY KEY (`data_type`,`data_code`)
) DEFAULT CHARSET=utf8 COMMENT='数据字典表';
受影响的行: 0
时间: 0.262s

然后查看建表 DDL:

SHOW CREATE TABLE data_dict_test;

打印结果:

CREATE TABLE `data_dict_test` (
  `data_type` varchar(32) NOT NULL COMMENT '数据字典类型',
  `data_code` tinyint(4) NOT NULL COMMENT '数据字典代码',
  `data_name` varchar(64) NOT NULL COMMENT '数据字典值',
  PRIMARY KEY (`data_type`,`data_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='数据字典表'

这次 SHOW CREATE TABLE 没有欺骗我们,明白给出的就是 InnoDB,尽管我们建表时没有指定。

笔者建议使用 SHOW TABLE STATUS 语句来查看特定表的存储引擎:

SHOW TABLE STATUS WHERE NAME = 'data_dict_test';

打印结果:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="SHOW TABLE STATUS WHERE NAME = 'data_dict_test'" />

參考资料

警惕 InnoDB 和 MyISAM 创建 Hash 索引陷阱的更多相关文章

  1. 【Mysql】mysql使用触发器创建hash索引

    概述 若设计的数据表中,包含较长的字段,比如URL(通常都会比较长),查询时需要根据该字段进行过滤: select * from table_xxx where url = 'xxxxxxx'; 为了 ...

  2. mysql InnoDB引擎是否支持hash索引

    看一下mysql官方文档:https://dev.mysql.com/doc/refman/5.7/en/create-index.html , 从上面的图中可以得知,mysql 是支持hash索引的 ...

  3. innodb和myisam对比及索引原理区别

    InnoDB和MyISAM是很多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,5.7之后就不一样了 1.事务和外键 InnoDB具有事务,支持4个事务隔离级别,回滚,崩溃修复能力和多版 ...

  4. MySQL的btree索引和hash索引的区别

    Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-T ...

  5. MySQL两大存储引擎InnoDB与MyISAM

    1.InnoDB存储引擎 MySQL5.5中InnoDB成为默认的存储引擎.InnoDB是事务型存储引擎,被设计用来处理大量的短期事务.它的性能和自动崩溃恢复特性,使得它在非事务场景中也很流行. 所以 ...

  6. B+索引、Hash索引、数据类型长度

    1.为什么在数据库中要用B树索引而不是Hash索引? Mysql Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这 ...

  7. Hash索引和BTree索引区别【转】

    索引是帮助mysql获取数据的数据结构.最常见的索引是Btree索引和Hash索引. 不同的引擎对于索引有不同的支持:Innodb和MyISAM默认的索引是Btree索引:而Mermory默认的索引是 ...

  8. mysql索引hash索引和b-tree索引的区别

    Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-T ...

  9. MySQL的btree索引和hash索引的区别 (转)

    Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-T ...

随机推荐

  1. 连类比事-category和extension

    extension看起来很像一个匿名的category,但是extension和有名字的category几乎完全是两个东西. extension在编译期决议,它就是类的一部分,在编译期和头文件里的@i ...

  2. [洛谷P3939]数颜色

    题目大意:有n个物品,每个物品有一个颜色.现在有两种操作:1.查询l-r内有多少颜色为c的物品并输出.2.将第x个物品和第x+1个交换.现在让你实现这些操作. 解题思路:首先一共有300000种颜色, ...

  3. javaweb集成swagger

    一.添加依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-sw ...

  4. ip iproute2的典型应用

    net-tools和iproute2的命令做对比,做到简单明了,分别演示如何去获取.配置和操作系统网络信息. 以下是net-tools和iproute2的大致对比: 4.1 ip link set-- ...

  5. Vue组件通信之Bus

    关于组件通信我相信小伙伴们肯定也都很熟悉,就不多说了,对组件通信还不熟悉的小伙伴移步这里. 在vue2.0中 $dispatch 和 $broadcast 已经被弃用.官方文档中给出的解释是: 因为基 ...

  6. Python学习笔记(二):字符串类型

    在上一篇随笔(https://www.cnblogs.com/g-qiang/p/10448813.html)中,说到 Python 有六种标准数据类型,而数字类型和字符串类型又是其中基本的数据类型. ...

  7. Github README.md中添加图片

    1.先把图片上传到你的项目中:然后在github网站上按路径打开图片,如下打开的图片链接: 2.复制图片的地址 3.然后在README.md写上: ![这里随便写文字](你刚复制的图片路径) 注意  ...

  8. 【CS Round 34】Max Or Subarray

    [题目链接]:https://csacademy.com/contest/round-34/summary/ [题意] 让你找一个最短的连续子串; 使得这个子串里面所有数字or起来最大; [题解] 对 ...

  9. FS,FT,DFT,DFS和DTFT的关系

    对于初学数字信号(Digital Signal Processing,DSP)的人来说,这几种变换是最为头疼的,它们是数字信号处理的理论基础,贯穿整个信号的处理. FS:时域上任意连续的周期信号可以分 ...

  10. JS 去除字符串中的最后一个字符

    var str = 'Hello World!'; str = str.substr(0,str.length-1); alert(str);