警惕 InnoDB 和 MyISAM 创建 Hash 索引陷阱
比方表 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 索引陷阱的更多相关文章
- 【Mysql】mysql使用触发器创建hash索引
概述 若设计的数据表中,包含较长的字段,比如URL(通常都会比较长),查询时需要根据该字段进行过滤: select * from table_xxx where url = 'xxxxxxx'; 为了 ...
- mysql InnoDB引擎是否支持hash索引
看一下mysql官方文档:https://dev.mysql.com/doc/refman/5.7/en/create-index.html , 从上面的图中可以得知,mysql 是支持hash索引的 ...
- innodb和myisam对比及索引原理区别
InnoDB和MyISAM是很多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,5.7之后就不一样了 1.事务和外键 InnoDB具有事务,支持4个事务隔离级别,回滚,崩溃修复能力和多版 ...
- MySQL的btree索引和hash索引的区别
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-T ...
- MySQL两大存储引擎InnoDB与MyISAM
1.InnoDB存储引擎 MySQL5.5中InnoDB成为默认的存储引擎.InnoDB是事务型存储引擎,被设计用来处理大量的短期事务.它的性能和自动崩溃恢复特性,使得它在非事务场景中也很流行. 所以 ...
- B+索引、Hash索引、数据类型长度
1.为什么在数据库中要用B树索引而不是Hash索引? Mysql Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这 ...
- Hash索引和BTree索引区别【转】
索引是帮助mysql获取数据的数据结构.最常见的索引是Btree索引和Hash索引. 不同的引擎对于索引有不同的支持:Innodb和MyISAM默认的索引是Btree索引:而Mermory默认的索引是 ...
- mysql索引hash索引和b-tree索引的区别
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-T ...
- MySQL的btree索引和hash索引的区别 (转)
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-T ...
随机推荐
- Node_进阶_8
Node进阶第八天 一.复习 Node.js特点:单线程.异步I/O(非阻塞I/O).事件驱动(事件环). 适合的程序:就是没有太多的计算,I/O比较多的业务. 举例:留言本.考试系统.说说.图片裁切 ...
- wepy框架的API的预加载$preload这功能阔以喔
优势:比 url 传递.或是 storage .或是 globalData 更方便 1:如 url 不能直接传一个 Object 要传的又要序列化与反序列化操作,麻烦(普通的单个变量还是挺便捷简单实在 ...
- [SCOI2016]美味(可持久化线段树)
可持久化trie树?好像和可持久化权值线段树差不多.. 如果这题没有那个\(x[i]\)这题就是一个裸的可持久化trie树. 仔细想想,多了这个\(x[i]\)之后有什么影响? 就是我们查询区间的时候 ...
- python购物车系统
购物车系统模拟:product_list = [ ('java',100), ('python',200), ('键盘',500), ('电脑',4000), ('mac Book',7000),]S ...
- Mac安装软件时,提示文件已损坏,需要移动到废纸篓的解决方法
1.修改系统偏好设置,安全性与隐私-->将“允许从以下位置下载的应用” ☑️任何来源. 2. mac10.12以上的系统一般没有“任何来源”这个选项,需打开terminnal终端,输入 sudo ...
- 10.29 工作笔记 ndk编译C++,提示找不到头文件(ndk-build error: string: No such file or directory)
ndk编译C++.提示找不到头文件(ndk-build error: string: No such file or directory) 被这个问题弄得愁眉苦脸啊.心想为啥一个string都找不到呢 ...
- 怎样实如今Windows下编写的代码,直接在Linux下编译
方法一: 怎样实如今Windows7下编写Linux程序.写完程序以后.不用复制文件,直接在Linux(RHEL6.5)机器上编译最新的代码. 1.首先将Windows的代码目录设置为共享目录: 2. ...
- POJ 2248 搜索
剪枝: 1.从后向前枚举 2.迭代加深 然后就0msAC了 //By SiriusRen #include <cstdio> using namespace std; int n,T,s[ ...
- java9新特性-6-多版本兼容jar包
1.官方Feature 238: Multi-Release JAR Files 2.使用说明 当一个新版本的Java出现的时候,你的库用户要花费数年时间才会切换到这个新的版本.这就意味着库得去向后兼 ...
- Glide加载圆形图片第一次只显示默认图片
Glide加载圆形图,又设置了默认图,很多时候第一次加载的时候只显示默认图.下面的方案可以解决.\ Glide.with(AudioDetailActivity.this) .load(cover) ...