MySQL存储引擎学习
目录:
1、存储引擎介绍
2、InnoDB及MyISAM性能对比
3、MyISAM和InnoDB的锁对比
4、两种存储引擎索引对比
说明:基于5.7.19的MySQL数据库。
图1.1 数据库版本
在Navicat for MySQL中进行测试:
输入sql:show engines;
图1.2 存储引擎类别
参数说明:
Engine:存储引擎名称
Support:MySQL是否支持该引擎
Comment:对该引擎的说明
Transaction:是否支持事务处理
XA:是否分布式交易处理XA规范
Savepoints:是否支持保存点,以便事务回滚到保存点
l InnoDB
适用于高性能和事务处理环境,支持外键,默认的存储引擎,“拆包即用”。
l MyISAM
适用于以只读为主的数据仓库、电子商务和企业应用中。MyISAM使用高级缓存和索引机制提高数据检索和索引速度,但不支持事务,不支持外键。
l Blackhole
适用于测试应用程序确实在写数据而又不希望在磁盘上存储任何数据的场景。Blackhole存储引擎满足一个特定的需求,如果启用了二进制日志,SQL语句将被写入日志,将Blackhole存储引擎作为复制拓扑中的中继或代理。在这种情况下,中继代理处理来自master的数据,并将这些数据发送到它的slave上去,但是它本身并不存储任何数据。
l CSV
适用于写CSV日志文件,将结构化业务数据快速导入电子表格。CSV存储引擎以表格形式创建、读取和写入逗号分隔值(CSV)文件。不提供任何索引机制,在存储和转换日期时间值时也存在某些问题,存储数据的效率不高,因此应该谨慎使用。
l Memory
适用于频繁访问而很少更改的静态数据的情况,例如邮编列表、省市区列表、分类列表等等,以及适用于利用快照技术访问分布数据或历史数据的数据库。Memory(有时被称为HEAP)是内存中的存储器,使用哈希机制检索频繁使用的数据,从而检索更快。由于数据存储在内存中,只在MySQL会话中有效,关机时数据被刷新并删除。
l Federated
适用于分布式或数据集环境。Federated存储引擎允许将多个数据库服务器的表连接起来。它不移动数据,也不要求远程表适用相同的存储引擎。目前Federated存储引擎在MySQL的大部分发行版中是禁用的。
l Archive
适用于存储和检索大量的很少访问的存档或历史数据。Archive存储引擎以压缩格式存储大量数据,不支持索引,只能通过表扫描访问。
l MRG_MYISAM
适用于非常大的数据库应用,如数据仓库,其中数据存储在一个或多个数据库的多个表中。MRG_MYISAM存储引擎的最优的特点就是快速,它将一个大表分割成许多不同的小表,存储在不同的磁盘上,把这些小表合并,然后同时访问它们,搜索和排序执行得更快,因为每个小表需要管理的数据变少了。
缺点:
l 必须使用相同的MyISAM表组成一个合成表;
l 替换操作不可用;
l 索引比单表的索引效率低。
说明:测试表中含有36个字段,并含有988218条记录。
InnoDB存储引擎的测试数据库名为Innodbtest,其中含有该表,表名为Innodbtable;MyISAM存储引擎的测试数据库名为Myisamtest,其中含有该表,表名为Myisamtable。
在MySQL中分别使用InnoDB及MyISAM存储引擎对该表进行测试,首先进行前期工作:
(1)将测试MyISAM存储引擎的表的存储引擎从默认的InnoDB修改为MyISAM:
alter table myisamtable engine=myisam;
图2.1 修改存储引擎
(2)修改数据库的字符编码,将其设置为utf-8
alter database myisamtest character set utf8;
alter database innodbtest character set utf8;
图2.2 修改InnoDB存储引擎测试库字符编码
图2.3 修改MyISAM存储引擎测试库字符编码
对两种存储引擎的一些特性进行测试:
l 存储结构
(1)InnoDB:
表数据都保存在一个大小为1.21GB的数据文件中——Innodbtable.ibd,与表相关的元数据信息存放在innodbtable.frm文件中,包括表结构的定义信息。db.opt中定义了数据库的一些定义信息。
图2.4 InnoDB磁盘存储目录
图2.5 db.opt文件内容
(2)MyISAM:
.frm文件:存储与表相关的元数据信息,包括表结构的定义信息等;
.MYD文件:大小为853.34MB,存放MyISAM表的数据。
.MYI文件:大小为34.11MB,存放MyISAM表的索引相关信息。
db.opt:定义了数据库的一些定义信息。
图2.6 MyISAM磁盘存储目录
图2.7 db.opt文件内容
l select
(1)InnoDB:
图2.8 InnoDB的select测试
(2)MyISAM:
图2.9 MyISAM的select测试
l insert
(1)InnoDB:
图2.10 InnoDB的insert测试
(2)MyISAM:
图2.11 MyISAM的insert测试
l update
(1)InnoDB:
图2.12 InnoDB的update测试
(2)MyISAM:
图2.13 MyISAM的update测试
l delete
(1)InnoDB:
图2.14 InnoDB的delete测试
(2)MyISAM:
图2.15 MyISAM的delete测试
l delete where
(1)InnoDB:
图2.16 InnoDB的delete where测试
(2)MyISAM:
图2.17 MyISAM的delete where测试
l count without where
(1)InnoDB:
图2.18 InnoDB的count without where测试
(2)MyISAM:
l group by
(1)InnoDB:
图2.20 InnoDB的group by测试
(2)MyISAM:
l 外键
创建一个新表,将测试表的主键作为新表的外键进行测试:
create table `foreigntest`(
`id` int primary key not null,
`taskid` varchar(64) not null,
`host` varchar(128) not null default '',
`month` char(8) not null,
constraint `fk_task_h_m` foreign key (`taskid`,`host`,`month`)
references `innodbtable`(`taskid`,`host`,`month`)
) charset=utf8mb4
(1)InnoDB:
图2.22 InnoDB的外键测试
(2)MyISAM:
图2.23 MyISAM的外键测试
总结如下表:
|
InnoDB |
MyISAM |
存储结构 |
.ibd:存放表数据; .frm文件:存储与表相关的元数据信息,包括表结构的定义信息等; 基于磁盘的资源是InnoDB表空间数据文件和它的日志文件,InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。 |
每个表在磁盘上存储成三个文件: .MYD文件:存放表的数据。 .MYI文件:存放表的索引相关信息。 .frm文件:存储与表相关的元数据信息,包括表结构的定义信息等; |
存储空间 |
InnoDB的表需要更多的内存和磁盘存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。 |
MyISAM可被压缩,存储空间较小。 |
可移植性 |
免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对困难了 |
由于MyISAM的数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作 |
事务安全 |
支持事务,具有事务(commit)、回滚(rollback)和崩溃修复能力 |
不支持事务,每次查询具有原子性 |
增 |
更优(0.15秒) |
(0.40秒) |
删(带where) |
(32.79秒) |
更优(16.51秒) |
全删 |
(263.86秒) |
更优(0.24秒) |
改 |
(0.20秒) |
更优(0.12秒) |
查 |
(139.75秒) |
更优(65.57秒) |
锁 |
支持表锁、行锁,行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。 |
只支持表锁 |
外键 |
支持 |
不支持 |
count without where |
没有保存表的具体行数,需要逐行扫描统计(70.88秒) |
更优,因为MyISAM保存了表的具体行数,只需简单读出。(0.09秒) |
group by |
(35.14秒) |
更优(4.75秒) |
附注:
[1]表空间:InnoDB用来组织与机器无关的文件的工具,包括数据、索引及回滚机制。默认情况下,所有表共享一个表空间(称为共享表空间)。共享表空间不会自动扩展成多个文件。默认情况下,一个表空间只占据单个文件,该文件随数据增加而增长。使用autoextend选项可以允许表空间创建新的文件。
[2]崩溃修复能力:InnoDB存储引擎使用两种基于磁盘的机制存储数据,即日志文件和表空间。在关机或死机之前,InnoDB会使用这些日志来重建数据恢复。在程序启动时,InnoDB读取日志并自动将脏页写入磁盘,从而在系统崩溃前恢复缓冲中的更新。
(1)表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
(2)行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
(3)对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写请求;MyISAM表的读和写操作之间,以及写和写操作之间是串行的(当一线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。)
(4)共享锁(s):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
(5)排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务取得相同的数据集共享读锁和排他写锁。
(6)对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁。
l InnoDB:
l 在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。
l InnoDB表使用的索引是聚集索引。聚集索引是一种数据结构,不仅存储索引,也存储数据本身。因此,一旦定位到索引中的某个值,就可以直接检索数据而无需额外的磁盘寻道。
l 主键索引或者表的第一个索引都采用聚集索引创建。
l InnoDB的所有辅助索引都引用主键作为data域。如果如果创建了辅助索引,聚集索引的关键字(主键、唯一键或行ID)也会存在辅助索引中,这样可以快速按照关键字查找和快速获取聚集索引中的原始数据。也就是如果使用主键列扫描辅助索引,则查询只需要用辅助索引就可以获取数据。
l MyISAM:
l 索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。使用B+树作为索引结构,叶节点的data域存放的是数据记录的地址。
l 在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。
l 主要区别:
l 主索引的区别:InnoDB的数据文件本身就是索引文件。而MyISAM的索引和数据是分开的。
l 辅助索引的区别:InnoDB的辅助索引data域存储相应记录主键的值而不是地址。而MyISAM的辅助索引和主索引没有多大区别。
附注:
B+树:对于一棵m阶B+树,具有如下特点:
l 有n棵子树的节点中含有n个关键字。
l 所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针。且叶子结点本身依照关键字的大小自小而大顺序链接。
l 所有的非终端结点可以看成索引部分,结点中仅含其子树(根结点)中的最大(或最小)关键字。
l 在B+树,不管查找成功与否,每次查找都是走了一条从根到叶子结点的路径。
l 树中每个结点最多含有m棵子树。