存储引擎是处理不同表类型SQL操作的MySQL组件。MySQL服务器采⽤可插拔的存储引擎架构, 在服务器运⾏时可以动态的加载和卸载。 查看当前服务器⽀持哪些存储引擎可以使⽤ show engines 语句, Engine 表⽰:存储引擎的名称, Support :表⽰当前服务器是否⽀持,值分别为: YES 、 NO 和 DEFAULT 分别表⽰,⽀持、不⽀持和当前设置或默认引擎,如下所⽰:
从中我们可以看到MySQL默认存储引擎为InnoDB
InnoDB 存储引擎
InnoDB是⼀款兼顾⾼可靠性和⾼性能的通⽤存储引擎。在MySQL8.0中默认的存储引擎是 InnoDB ,使⽤ CREATE TABLE 语句创建表时,在没有修改默认存储引擎或明确指定其他存储引擎时,将创建⼀个 InnoDB 的表。 InnoDB存储引擎的特性如下:创建InnoDB表
# 选择⽬标数据库
use test_db
# 创建⼀个使⽤InnoDB存储引擎的表
CREATE TABLE t_innodb (
id int(11) PRIMARY KEY AUTO_INCREMENT,
name varchar(20)
) ENGINE = InnoDB;
当创建⼀个存储引擎为
InnoDB
的表时,会在
data_dir/test_db
⽬录下⽣成⼀个⽤来存储真实数据的物理⽂件,命名格式为
表名
.ibd
,以当前为例会在
/var/lib/mysql/test_db
⽬录下⽣成⼀个
t_innodb.ibd
的表空间数据⽂件,这个文件是InnoDB存储引擎用来存储表数据和索引的物理文件。
如果想测试使⽤其他存储引擎表中的数据在InnoDB表中的⼯作情况,在确保不影响原始表的情况
下,我们可以使⽤以下⽅式创建⼀张InnoDB表
create table ... engine=InnoDB as select * from other_engine_table;
InnoDB 的主要优势
- DML操作遵循ACID模型,事务具有提交、回滚和崩溃恢复功能,以保护⽤⼾数据。如果发⽣意外⽽崩溃,⽆论当时数据库发⽣了什么,都不需要在重启数据库后执⾏任何特殊操作。InnoDB 的崩溃恢复功能会⾃动完成崩溃之前提交的更改,并撤消崩溃前正在进⾏但未提交的更改,从⽽允许我们从中断的地⽅继续执⾏。
- ⽀持⾏级锁,提⾼了多⽤⼾的读取并发性和性能。
- InnoDB 存储引擎维护了⼀个⾃⼰的缓冲池,访问数据时在内存中缓存表和索引数据,对于经常使⽤的数据直接从内存中处理,⼤幅提升了效率。在专⽤数据库服务器上,通常会将⾼达 80% 的物理内存分配给缓冲池。
- InnoDB表优化了基于主键的查询,每个InnoDB表都有⼀个称为聚簇索引的主键索引,实现通过最少的磁盘I/O完成对主键的查找。
- 为了保持数据完整性, InnoDB ⽀持 FOREIGN KEY (外键)约束。在进⾏插⼊、更新和删除数据时确保相关表之间的⼀致性
- 当从表中反复查询相同的⾏时,⾃适应哈希索引会⾃动接管这些查询,此时查询效率和哈希表相同。
InnoDB表的最佳实践
- 为表中最频率查询的列(或多个列)指定主键(或复合主键),如果没有明显的主键,则创建⼀个⾃增的列做为主键。
- 从多个表中根据相同的ID查询数据,建议使⽤表连接。可以在连接的列上定义外键,并在每个表中使⽤相同的数据类型声明这些列。添加外键可以确保被引⽤的列使⽤索引,从⽽提⾼性能。
- 在每秒提交数百次事务的服务器上,结合存储设备的写⼊速度,关闭事务的⾃动提交,通过系统变量 autocommit=OFF 设置。
- 把相关的DML操作⽤ START TRANSACTION 和 COMMIT 语句括在⼀起,分组为事务⼀起提交或回滚。
- 不要使⽤ LOCK TABLES 语句,InnoDB可以在不牺牲可靠性和⾼性能的情况下处理多个会话同时对⼀个表进⾏读写操作。
MyISAM 存储引擎
使⽤MyISAM存储引擎的表占⽤空间很⼩,但是由于使⽤表级锁定,所以限制了读/写操作的性能,通常⽤于中⼩型的Web应⽤和数据仓库配置中的只读或主要是读的场景。 MyISAM 存储引擎的特性如下:MyISAM和InnoDB是MySQL数据库中两种常用的存储引擎,它们在数据存储结构、事务支持、锁的支持、外键支持、主键观念、性能和优化方式等方面存在明显的差异。以下是它们的主要区别:
特性 | MyISAM | InnoDB |
---|---|---|
事务支持 | 不支持 | 支持 |
外键支持 | 不支持 | 支持 |
锁的支持 | 表级锁 | 行级锁 |
主键观念 | 可以不定义主键 | 必须有主键 |
数据存储结构 | 索引和数据文件分离 | 数据文件和索引文件在一起 |
创建MyISAM 表
在MySQL 8.0中 InnoDB 是默认引擎,所以在创建表时需要指定 ENGINE=MyISAM :# 创建⼀个使⽤MyISAM存储引擎的表
CREATE TABLE t_myisam (
id int(11) PRIMARY KEY AUTO_INCREMENT,
name varchar(20)
) ENGINE = MyISAM;
创建
MyISAM
表会根据表名⽣成三个不同后缀名⽂件,分别是以
.MYD
(
MYData
)为后缀的数据
⽂件,以
.MYI
(
MYIndex
) 为后缀的索引⽂件,以
.sdi
为后缀的表信息描述⽂件(JSON格式)
MyISAM 的主要优势
- MyISAM表的最⼤⾏数为 (2^32)^2 及 (1.844E+19) ⾏
- 每个MyISAM表最多可以创建64个索引,每个索引最多可以包含16个列
- ⽀持并发插⼊
- 通过 create table 创建表时,指定 DATA DIRECTORY=PATH 和 INDEX,DIRECTORY=PATH 将数据⽂件和索引⽂件放在不同设备的不同⽬录中,从⽽提⾼访问速度
- BLOB 和 TEXT 数据类型的列也可以被索引
- 在索引列中允许使⽤NULL值
- 如果mysqld启动时设置了 myisam_recover_options 系统变量,那么MyISAM表在打开时进⾏会⾃查,如果上⼀次表没有正确关闭将会修复
- 表中 VARCHAR 和 CHAR 列的⻓度总和最多可达64KB
- UNIQUE 约束的⻓度不受限制
MyISAM 表存储格式
- MyISAM 表⽀持三种不同的存储格式,其中 FIXED 静态(固定)格式和 DYNAMIC 动态格式,根据使⽤的列类型⾃动选择,第三种是压缩格式,只能使⽤ myisampack 实⽤程序⽣成并且是只读格式。
- 当表中没有 BLOB 或 TEXT 数据类型的列,在使⽤ CREATE TABLE 或 ALTER TABLE 语句创建或修改表时,可以结合 ROW_FORMAT 表选项将表格式设置为 FIXED 或 DYNAMIC 。
- 使⽤ myisamchk 实⽤⼯具对已压缩的MyISAM进⾏解压操作, myisamchk --unpack 。
静态格式(Fixed-Length)表
静态格式是 MyISAM 表的默认格式,当表不包含可变⻓度的列 ( VARCHAR 、 VARBINARY 、 BLOB 或 TEXT ) 时使⽤,每⾏都使⽤固定数量的字节存储。 MyISAM 的三种存储格式中,静态格式是最简单和最安全的(最不容易损坏),同时也是最快的磁盘格式,因为每⾏的⻓度固定,根据索引中的⾏号乘以⾏⻓度就可以计算出⾏位置,此外,每次读取固定数量的⾏也⾮常的⾼效。 静态格式表具有以下特点:- CHAR 和 VARCHAR 类型的列⽤空格填充到指定的列宽, BINARY 和 VARBINARY 类型的列⽤ 0x00 字节填充到列宽
- 每个允许为NULL的列,都⽤⼀个 1 BIT 的额外空间记录当前列是否为空
- 速度⾮常快,且易于缓存
- 崩溃后易于重建,因为⾏都位于固定位置
- 通常需要⽐动态格式表更多的磁盘空间
动态格式表
当表中包含可变⻓度列( VARCHAR 、 VARBINARY 、 BLOB 或 TEXT )或者在创建表时使⽤ ROW_FORMAT=DYNAMIC 选项,则表格式为动态存储格式 动态格式表具有以下特点:- 列类型是字符串,且⻓度⼤于等于4,⻓度都是动态的
- 每⼀⾏都有⼀个标志来指⽰⾏有多⻓,当因更新操作⽽变得更⻓时,数据可能存储在不连续的空间,可以使⽤ OPTIMIZE TABLE table_name 语句或 myisamchk -r 对表进⾏碎⽚整理
- 每个允许为NULL的列,都⽤⼀个 1 BIT 的额外空间记录当前列是否为空
- 每⾏前⾯都有⼀个 bitmap (位图),⽤来记录包含空字符串或0的列,如果字符串类型的列⻓度为零,或者数字列的值0,则在位图中标记并且不会保存到磁盘
- 通常磁盘空间占⽤⽐固定⻓度表要少很多
- 每⾏都单独压缩,每列都可能⽤单独的⽅式进⾏压缩
压缩格式表
压缩存储格式是使⽤myisampack⼯具⽣成的只读格式数据表,压缩表可以⽤ myisamchk解压缩。 压缩格式表具有以下特点:- 压缩表占⽤很少的磁盘空间,最⼤限度地减少了磁盘使⽤
- 可以⽤于固定⻓度或动态⻓度⾏
- 压缩表是只读的,因此不能在表中更新或添加数据
MEMORY存储引擎
使⽤MEMORY存储引擎创建的表,内容存储在内存中。当服务器由于硬件问题、断电或其他原因崩溃时数据会丢失,因此这些表仅⽤作临时⼯作区或从其他表中提取数据的只读缓存。使用场景
- 涉及瞬时、⾮关键数据的操作,例如会话管理或需要缓存的数据,当服务器停⽌或重新启动时, MEMORY 表中的数据会丢失;
- ⽤于快速访问和低延时,数据量可以完全放在物理内存中,不使⽤虚拟内存
- 只读或以读为主的数据访问场景(有限的更新)
- 使⽤固定⻓度的存储格式,可变⻓度类型,例如 VARCHAR 使⽤固定⻓度存储
- 不能包含 BLOB 或 TEXT 列
- ⽀持 AUTO_INCREMENT 的列
- ⾮ TEMPORARY MEMORY 表在所有客⼾端之间共享
- ⽀持 HASH 索引(默认)和 BTREE 索引
- 不⽀持表分区
- 由于使⽤单线程,在⾼负载的场景下可能会涉及严重的锁竞争,特别是在多个客⼾端并发执⾏更新操作的情况下,性能并不⼀定会⽐ InnoDB 更快
创建MEMORY表
在MySQL 8.0中 InnoDB 是默认引擎,所以在创建表时需要指定 ENGINE= MEMORY :# 创建⼀个使⽤MEMORY存储引擎的表
CREATE TABLE t_memory1 (
id int(11) PRIMARY KEY AUTO_INCREMENT,
name varchar(20)
) ENGINE = MEMORY;
由于数据在内存中保存,所以
MEMORY
表不会在磁盘上⽣成数据⽂件,表结构保存在.sdi
⽂件中
创建表并加载数据
# 从其他表中加载数据
CREATE TABLE t_memory ENGINE=MEMORY select * from student;
查看内存表 t_memory 中的数据
select * from t_memory;
内存管理
删除单⾏数据,不会回收内存,只有删除整个表时才会回收内存。当不需要内存表的内容时,要释 放该表所使⽤的所有内存,可以执⾏ delete 或 truncate table 删除所有⾏,或者使⽤ drop table 删除表。如果要释放被删除⾏所使⽤的内存,使⽤ ALTER TABLE ENGINE= MEMORY 命令强制重建表 max_heap_table_size 系统变量设置了内存表的最⼤⼤⼩限制,默认为16MB,要控制单个表的最⼤⼤⼩,在创建每个表之前设置该变量的 session 值。(不要改变全局的 max_heap_table_size 值,除⾮要明确设置所有客⼾端创建的内存表),下⾯的⽰例创建了两个内存表,最⼤⼤⼩分别为 1MB 和 2MB :# 指定第⼀张表的内存最⼤值为1MB
mysql> SET max_heap_table_size = 1024*1024;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t1 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.01 sec)
# 指定第⼆张表的内存最⼤值为2MB
mysql> SET max_heap_table_size = 1024*1024*2;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t2 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.00 sec)
每次重启服务器内存表中的数据将被清空,内存表中的数据永远不会写⼊磁盘。
CSV存储引擎
CSV是逗号分隔值(Comma-Separated Values)的缩写,以纯⽂本形式存储表格数据。创建CSV表
在MySQL 8.0中 InnoDB 是默认引擎,所以在创建表时需要指定 ENGINE=CSVCREATE TABLE t_csv (id INT NOT NULL, content CHAR(100) NOT NULL) ENGINE = CSV;
创建
CSV
表时,服务器会创建三个⽂件,其中以
.CSV
为扩展名的⽂件⽤于以逗号分隔值的格式
保存数据;扩展名为
.CSM
的⽂件,⽤于存储表的状态和表中的⾏数;以
.sdi
为后缀的表信息描述⽂件(JSON格式)
CSV表中的数据
向表中插⼊数据
INSERT INTO t_csv VALUES(1,'record one'),(2,'record two');
由于
.CSV
是⽂件格式的⽂件,我们在命令⾏查看⽂件内容如下:
CSV 表的修复和检查
CSV 存储引擎⽀持使⽤ CHECK TABLE 和 REPAIR TABLE 语句来验证或修复损坏的 CSV 表。CHECK TABLE t_csv; # 检查CSV表
- 当⽤⽂本编辑器打开t_csv.CSV⽂件,并写⼊⼀条新数据,如下所⽰:
- 再次执⾏查询语句发现没有第三条数据,这是由于.CSM⽂件中并没有记录新增的⾏,可以使⽤ REPAIR TABLE 语句修改表内容和CSM⽂件
REPAIR TABLE t_csv; # 修复CSV表
ARCHIVE存储引擎
使⽤ ARCHIVE 存储引擎创建的表,存储⼤量不被索引的数据且占⽤空间很⼩,⼀般⽤于归档数据的存储。 ARCHIVE存储引擎的特性如下:- ⽀持 INSERT , REPLACE 和 SELECT ,但不⽀持 DELETE 和 UPDATE
- ⽀持列的 AUTO_INCREMENT 属性,该列可以有唯⼀约束,且⼿动指定的值不能⼩于该列的最⼤值
- 不⽀持索引,在任何列上尝试建⽴索引都会报错
- 插⼊时,数据将被压缩, ARCHIVE 引擎使⽤ zlib ⽆损数据压缩; INSERT 语句只是将数据写⼊压缩缓冲区并且根据需要刷新到磁盘,当执⾏ SELECT 时会强制刷新缓冲区
- 检索时,按需要进⾏解压缩,不⽀持⾏缓存
- SELECT操作执⾏全表扫描,找出当前查询的⾏,并读取⾏数
- 使⽤⾏级锁定
- 不⽀持表分区
创建ARCHIVE表
在MySQL 8.0中 InnoDB 是默认引擎,所以在创建表时需要指定 ENGINE= ARCHIVE# 创建⼀个使⽤ARCHIVE存储引擎的表
CREATE TABLE t_archive (
id int(11) UNIQUE AUTO_INCREMENT,
name varchar(20)
) ENGINE = ARCHIVE;
创建
ARCHIVE
表会根据表名⽣成两个不同后缀名⽂件,分别是以
.ARZ
为后缀的数据⽂件,以
.sdi
为后缀的表信息描述⽂件(JSON格式),
.ARN
⽂件在优化操作期间可能会出现
MERGE存储引擎
MERGE存储引擎,也称为MRG_MyISAM引擎,允许MySQL DBA或开发⼈员在逻辑上将⼀系列相 同的MyISAM表分组,并将它们作为⼀个对象引⽤。适⽤于VLDB(Very Large Data Bases)环境,如数据仓库。这⾥的相同表⽰所有表中的列都有相同的数据类型和索引信息。⽰意图如下:创建MERGE表
在MySQL 8.0中 InnoDB 是默认引擎,所以在创建表时需要指定 ENGINE=MERGE 创建MERGE表必须指定 UNION=(list-of-tables) 选项,表⽰要使⽤哪些MyISAM表;还可以通过指定 INSERT_METHOD 选项来控制如何对MERGE表进⾏插⼊操作, FIRST 或 LAST 值分别表⽰在第⼀个或最后⼀个基础表中进⾏插⼊,如果没有指定 INSERT_METHOD 选项,或者指定它的值为 NO ,那么在 MERGE 表中执⾏插⼊将会报错# 创建基础表1
CREATE TABLE test_m1 (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
content CHAR(20)) ENGINE=MyISAM;
# 创建基础表2
CREATE TABLE test_m2 (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
content CHAR(20)) ENGINE=MyISAM;
# 向基础表中写⼊数据
INSERT INTO test_m1 (content) VALUES ('Testing1'),('table1'),('test_m1');
INSERT INTO test_m2 (content) VALUES ('Testing2'),('table2'),('test_m2');
# 创建MERGE表
CREATE TABLE t_merge (
id INT NOT NULL AUTO_INCREMENT,
content CHAR(20), INDEX(id))
ENGINE=MERGE UNION=(test_m1,test_m2) INSERT_METHOD=LAST;
创建
MERGE
表时,会在磁盘上创建⼀个
.mrg
⽂件,其中包含了基础MyISAM表的名称,MERGE
的表格式存储在MySQL数据字典中,
.sdi
为后缀的表信息描述⽂件
基础表中的 id 列作为 PRIMARY KEY 索引,但在MERGE表中并不作为主键,但是可以被索引。因为 MERGE 表不能对基础表集强制唯⼀性,类似的,基础表中具有 UNIQUE 索引的列可以在MERGE 表中被索引,但不能作为唯⼀约束。
要将MERGE表重新映射到不同的MyISAM基础表集合,您可以使⽤以下⽅法之⼀:- 删除MERGE表并重新创建;
- 使⽤ ALTER TABLE tbl_name UNION=(…) 修改基础表的集合,ALTER TABLE…UNION=() 列表为空时,表⽰删除所有基础表
FEDERATED 存储引擎
默认不⽀持,可以在启动mysql时通过命令⾏选项 --federated 或选项⽂件的配置来启动
允许访问远程MySQL数据库中的数据,在不使⽤复制或集群技术的情况下, FEDERATED 存储引擎可以实现对远程MySQL数据库中数据的访问,以多个物理服务器为基础创建⼀个逻辑数据库,当查询 FEDERATED 表时,将会从远程数据库获取数据,⾮常适合分布式或数据集市环境。如图所⽰: 5.8.1 创建FEDERATED表- 本地配置⽂件 /etc/mysql/my.cnf 中的 [mysqld] 节点下加⼊ federated=1 来启⽤ FEDERATED 引擎,之后使用 systemctl restart mysql 重启MySQL服务。
# 配置⽂件路径 /etc/mysql/mysql.cnf
[mysqld]
federated=1 #加⼊配置
- 重启本地数据库服务并查看 FEDERATED 引擎是否启⽤
- 在远程服务器上创建表并添加部分数据
use test_db;//选择一个数据库,若无则创建
CREATE TABLE t_federated (
id INT(20) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
INDEX name (name)
)
ENGINE=MyISAM
DEFAULT CHARSET=utf8mb4;
select * from t_federated;
- 创建一个与远程服务器通信的用户
- 本地服务器上的建表语句
CREATE TABLE t_federated (
id INT(20) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
INDEX name (name)
)
ENGINE=FEDERATED
DEFAULT CHARSET=utf8mb4
CONNECTION='scheme://user_name[:password]@host_name[:port_num]/db_name/tbl_name'; # 指定远程服务器的连接
连接字符串的格式:
scheme
://
user_name
[:
password
]@
host_name
[:
port_num
]/
db_name
/
tbl_name
- scheme : 连接协议,⽬前只⽀持mysql;
- user_name : ⽤于连接远程服务器的⽤⼾名,注意:这个⽤⼾在远程服务器已创建,并授予了相应的操作权限;
- password :⽤⼾的密码;
- host_name :远程服务器的IP地址;
- port_num :远程服务器MySQL服务的端⼝号;
- db_name : 远程表所在的数据库名;
- tbl_name :远程表名,本地表名与远程表名可以不同,但建议保持⼀致。