小阿轩-yx存储引擎MyISAM和InnoDB
存储引擎概述
什么是存储引擎
- 是数据库底层软件组件,数据库管理系统使用数据引擎进行创建、查询、更新和删除数据操作
- 不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能
- 使用不同的存储引擎还可以获得特定的功能
- MySQL中的数据用不同的技术存储在文件(或者内存)中。
- 选择不同的技术,能够获得额外的速度或者功能,改善应用的整体性能。
现在许多数据库管理系统都支持多种不同的存储引擎。MySQL 的核心就是存储引擎
MySQL 支持的存储引擎
- MySQL 支持多种类型的数据库引擎,可根据各个引擎的功能和特性为不同的数据库提供各自不同的适应性和灵活性
- MySQL中,可以利用 Show ENGINES 语句来显示可用的数据库引擎和默认引擎。
- MySQL 中,不需要在整个服务器中使用同一种存储引擎,针对具体的要求对每个表使用不同的存储引擎
- 针对具体的要求,可以对每一个表使用不同的存储引擎
MySQL 5.7 支持的存储引擎
- InnoDB
- MyISAM
- Memory
- Merge
- Archive
- Federated
- CSV
- BLACKHOLE 等
可以使用SHOW ENGINES语句查看系统所支持的引擎类型
如何选择 MySQL 存储引擎
不同存储引擎都有各自特点,以适应不同的需求
每个存储引擎提供不同的功能
功能 | MyISAM | MEMORY | InnoDB | Archive |
存储限制 | 256TB | RAM | 64TB | None |
支持事务 | No | No | Yes | No |
支持全文索引 | Yes | No | No | No |
支持树索引 | Yes | Yes | Yes | No |
支持哈希索引 | No | Yes | No | No |
支持数据缓存 | No | N/A | Yes | No |
支持外键 | No | No | Yes | No |
提示
- InnoDB 事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键。MySQL 5.5.5 之后,InnoDB 作为默认存储引擎。
- MyISAM 是基于 ISAM 的存储引擎,并对其进行扩展,是在 Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事务。
- MEMORY 存储引擎将表中的数据存储到内存中,为查询和引用其他数据提供快速访问。
可以根据以下原则选择 MySQL 存储引擎
- 如果要提供提交、回滚和恢复的事务安全(ACID 兼容)能力,并要求实现并发控制,InnoDB 是一个很好的选择。
- 如果数据表主要用来插入和查询记录,则 MyISAM 引擎提供较高的处理效率。
- 如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存的 MEMORY 引擎中,MySQL 中使用该引擎作为临时表,存放查询的中间结果。
- 如果只有 INSERT 和 SELECT 操作,可以选择Archive 引擎,Archive 存储引擎支持高并发的插入操作,但是本身并不是事务安全的。Archive 存储引擎非常适合存储归档数据,如记录日志信息可以使用 Archive 引擎。
提示
-
使用哪一种引擎要根据需要灵活选择,一个数据库中多个表可以使用不同的引擎以满足各种性能和实际需求。使用合适的存储引擎将会提高整个数据库的性能。
MySQL 默认存储引擎
InnoDB
-
是系统的默认引擎
-
支持可靠的事务处理
修改数据库临时的默认存储引擎语法
SET default_storage_engine=< 存储引擎名 >
操作存储引擎
查看mysql支持的存储引擎
MariaDB [(none)]> show engines;
+--------------------+--------+--------+--------------+----+------------+
| Engine | Support| Comment| Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------+
| InnoDB | DEFAULT| Percona-XtraDB, Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| MRG_MYISAM | YES | Collection of identical MyISAM tables| NO | NO | NO
| MyISAM | YES | Non-transactional engine with good performance and small data footprint | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | PERFORMANCE_SCHEMA | YES |PERFORMANCE_SCHEMA | NO | NO |
| CSV | YES | Stores tables as CSV files | NO | NO | NO
| ARCHIVE |YES|gzip-compresses tables for a low storage footprint | NO | NO | NO
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| FEDERATED | YES | Allows to access tables on other MariaDB servers, supports transactions and more| YES | NO | YES |
| Aria | YES | Crash-safe tables with MyISAM heritage| NO| NO | NO |
+--------------------+--------+--------+--------------+-----+------------+----------------+
10 rows in set (0.00 sec)
这些技术中的每一种都使用不同的
- 存储机制
- 索引技巧
- 锁定水平
最终提供以下功能和能力
- 广泛的
- 不同的
不同的技术以及配套的相关功能在 MySQL 中被称作:存储引擎(也称作表类型)
MySQL 默认配置了许多不同的存储引擎
可以预先设置或者在 MySQL 服务器中启用
选择适用于服务器、数据库、表格的存储引擎,可以在存储信息、检索数据时,提供最大的灵活性
关系数据库表
- 用于存储和组织信息的数据结构
- 可以将表理解为由行和列组成的表格
- 类似于 Excel电子表格的形式
特点
- 有的表简单
- 有的表复杂
- 有的表根本不用来存储任何长期数据
- 有的表读取时非常快,但是插入数据时却很差
MySQL
- 提供了很多种类型的存储引擎(或者说不同的表类型)
- 根据对数据处理的需求,可以选择不同的存储引擎,从而最大限度的利用 MySQL 强大的功能
MySQL 客户端中,查看 MySQL 支持的引擎
mysql>show engines;
MyISAM 存储引擎
- 不支持事务
- 也不支持外键
特点
- 访问速度快
- 对事务完整性没有要求
以 SELECT、INSERT 为主的应用基本都可以使用这个引擎来创建表
每个 MyISAM 表在磁盘上存储成3个文件
其中文件名和表名都相同
扩展名分别为
- frm(存储表定义)
- MYD(MYData,存储数据)
- MYI(MYIndex,存储索引)
不同的目录放置
- 数据文件
- 索引文件
- 可平均分配 IO,获取更快的速度
要指定数据文件和索引文件的路径,需要在创建表的时候通过语句
- DATA DIRECTORY
- INDEXDIRECTORY
- 文件路径需要使用绝对路径
每个 MyISAM 表都有一个标志,服务器或 myisamchk 程序在检査 MyISAM 数据表时会对这个标志进行设置。
MyISAM 表还有一个标志用来表明该数据表在上次使用后是不是被正常的关闭了。
- 如果服务器意外宕机或崩溃,这个标志可以用来判断数据表是否需要检查和修复。
- 如果想让这种检查自动进行,可以在启动服务器时使用--myisam-recover 实现。
这会让服务器在每次打开一个MyISAM数据表时自动检查数据表的标志并进行必要的修复处理。
MyISAM 类型的表可能会损坏
可以使用 CHECK TABLE 语句
- 检査 MyISAM 表的健康
修复一个损坏的 MyISAM 表语句
- REPAIR TABLE
支持3种不同存储方式
- 静态(固定长度)表
- 动态表
- 压缩表
静态表
- 默认的存储格式
- 字段都是非可变字段
- 每个记录都是固定长度
这种存储方式的优点
- 存储非常迅速
- 容易缓存
- 出现故障容易恢复
缺点
- 占用的空间通常比动态表多
数据存储时会根据列定义的宽度定义补足空格
但是在访问的时候并不会得到这些空格,这些空格在返回给应用之前已经去掉。
注:某些情况下可能需要返回字段后的空格,而使用这种格式时后面的空格会被自动处理掉。
动态表
包含
- 可变字段
- 记录不是固定长度
这样存储的优点
- 占用空间较少
- 频繁的更新、删除记录会产生碎片
- 需要定期执行 OPTIMIZE TABLE 语句或 myisamchk -r命令来改善性能
- 出现故障时恢复相对比较困难
压缩表
- 由 myisamchk 工具创建
- 占据非常小的空间,因为每条记录都是被单独压缩的,所以只有非常小的访问开支
InnoDB 存储引擎
- 是一个健壮的事务型存储引擎
- 已经被很多互联网公司使用
- 为用户操作非常大的数据存储提供了一个强大的解决方案
- 还引入了行级锁定和外键约束
MySQL 从5.5.5版本开始
- 默认的存储引擎为 InnoDB
以下场景中使用 InnoDB 存储引擎是最理想选择
- 更新密集的表:InnoDB存储引擎特别适合处理多重并发的更新请求
- 事务:InnoDB 存储引擎是支持事务的标准 MySQL存储引擎。
- 自动灾难恢复:与其它存储引擎不同,InnoDB表能够自动从灾难中恢复。
- 外键约束:MySQL 支持外键的存储引擎只有InnoDB。
- 支持自动增加列 AUTO INCREMENT 属性。
Innodb 的数据文件
- ibd:数据表的数据文件
- frm:数据表的元数据
- opt:存储的是mysql的一些配置信息,如编码、排序的信息等
不错的选择用于
- 事务支持
- 有较高的并发读取频率
MyISAM 和 InnoDB 两种存储引擎
区别
- InnoDB 支持事务,MyISAM 不支持,这一点是非常重要。事务是一种高级的处理方式,如对一些表中的列进行增删改的过程中只要哪个出错还可以回滚还原,而 MyISAM就不可以。
- MyISAM 适合查询、插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用。
- InnoDB 支持外键,MyISAM 不支持。
- MySQL5.5.5 以后,InnoDB 是默认引擎。
- MySQL 从 5.6 版本开始 InnoDB 引擎才支持 FULLTEXT 类型的索引
- InnoDB 中不保存表的行数,如 select count(*)from table 时,InnoDB 需要扫描一遍整个表来计算有多少行,但是MVISAM 只要简单的读出保存好的行数即可。需要注意的是,当 count(*)语句包含 where 条件时 MyISAM 也需要扫描整个表。
- 对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM 表中可以和其他字段一起建立组合索引。
- 清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表。
- InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like"%lee%';)。
关于 MyISAM 与 InnoDB 选择使用
- 如果应用程序一定要使用事务,要选择 InnoDB 引擎。但要注意,InnoDB的行级锁是有条件的。在 where 条件没有使用主键时,照样会锁全表。
- 如果应用程序对查询性能要求较高,就要使用MyISAM了。MyISAM 索引和数据是分开的,而且其索引是压缩的,可以更好地利用内存。所以它的查询性能明显优于 InnoDB.压缩后的索引也能节约一些磁盘空间。
MySQL 数据库提供的两种存储引擎
- MyISAM
- InnoDB
InnoDB
- 支持一些关系数据库的高级功能,如事务功能和行级锁,MyISAM 不支持。
MyISAM
- 性能更优
- 占用的存储空间少
修改默认的存储引擎
创建表,并查看默认用的存储引擎
mysql> create database auth;
mysql> use auth
mysql> CREATE TABLE t1 (user_name CHAR(16), user_passwd CHAR(48));mysql> show table status from auth where name='t1'\G
通过 alter table 修改
mysql> alter table t1 engine=MyISAM;
mysql> show table status from auth where name='t1'\G
通过配置文件修改
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
# 添加下面语句
default-storage-engine=MyISAM
[root@localhost ~]# systemctl restart mysqld
[root@localhost ~]# mysql -uroot -ppwd123
mysql> use authmysql> CREATE TABLE t2 (user_name CHAR(16), user_passwd CHAR(48));
mysql> show table status from auth where name='t2'\G
注:通过配置文件修改的方法,对以前的老表不会有影响,只会影响以后新创建的表,并且在创建表时没有指定存储引擎的情况。
通过 create table 创建表时指定存储引擎
mysql> use auth
mysql> create table t3 (id int(10),name char(20)) engine=INNODB;
mysql> show table status from auth where name='t3'\G
临时修改默认的存储引擎
SET default_storage_engine=< 存储引擎名 >
MyISAM 和 InnoDB 实例比较
选择两个比较重点的存储引擎实验下速度之类的性能对比
创建两张表分别以MyIsam和InnoDB作为存储引擎
create database test;
use test;create table tm(id int(20) primary key auto_increment,name char(30)) engine=myisam;create table ti(id int(20) primary key auto_increment,name char(30)) engine=innodb;mysql> show create table tm\G
mysql> show create table ti\G
两张表内容是一致的但是存储引擎不一样
插入一千万数据,来比较两个存储引擎的存储效率
这里不能手动的插入,创建一个存储过程插入一千万的数据
设置sql语句结束符
mysql> delimiter $
注:delimiter $语句是设置sql语句的结束符为“$”
创建两个存储过程
mysql> create procedure insertm()
begin
set @i=1;
while @i<=10000000
do
insert into tm(name) values(concat("wy",@i));
set @i=@i+1;
end while;
end
$
mysql> create procedure inserti()
begin
set @i=1;
while @i<=10000000
do
insert into ti(name) values(concat("wy",@i));
set @i=@i+1;
end while;
end
$
mysql> delimiter ;
注:delimiter ;语句是设置sql语句的结束符为“;”
利用存储过程向两个表添加数据
插入(一千万条)MyIsam存储引擎的表中的时间
mysql> call insertm;
Query OK, 0 rows affected (1 min 49.74 sec)
插入(一千万条)InnoDB存储引擎的表中的时间
mysql> call inserti;
Query OK, 0 rows affected (13 min 32.96 sec)
比较结果:
MyIsam存储引擎在写入方面有优势
查询数据总数目
InnoDB的SQL语句的分析
MariaDB [test]> desc select count(*) from ti\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: titype: index
possible_keys: NULLkey: PRIMARYkey_len: 4ref: NULLrows: 1000160Extra: Using index
1 row in set (0.00 sec)
MyIsam(它的数据存储在其他的表中所以这里是没有影响行数的)的SQL语句的分析
riaDB [test]> desc select count(*) from tm\G;
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: NULLtype: NULL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: NULLExtra: Select tables optimized away
1 row in set (0.00 sec)
MyIsam使用专门的MYD表存储数据,所以这里没有查询结果
MyISAM存储引擎会使数据表生成3个文件
-
frm文件存储表的定义
-
MYD文件是数据文件
-
MYI文件是索引文件
查询某一范围的数据
没有索引的列
MariaDB [test]> select * from tm where name>"wy100" and name <"wy10000000";
+---------+-----------+
| id | name |
+---------+-----------+
| 1000 | wy1000 |
| 10000 | wy10000 |
| 100000 | wy100000 |
| 1000000 | wy1000000 |
+---------+-----------+
4 rows in set (0.68 sec)
MariaDB [test]> select * from ti where name>"wy100" and name <"wy10000000";
+---------+-----------+
| id | name |
+---------+-----------+
| 1000 | wy1000 |
| 10000 | wy10000 |
| 100000 | wy100000 |
| 1000000 | wy1000000 |
+---------+-----------+
4 rows in set (2.71 sec)
MariaDB [test]> select * from tm where name="wy9999999";
+---------+-----------+
| id | name |
+---------+-----------+
| 9999999 | wy9999999 |
+---------+-----------+
1 row in set (0.42 sec)
MariaDB [test]> select * from ti where name="wy9999999";
+---------+-----------+
| id | name |
+---------+-----------+
| 9999999 | wy9999999 |
+---------+-----------+
1 row in set (2.38 sec)
无索引查询MyIsam有优势
有索引的列
使用MyIsam存储引擎的表
select * from tm where id>10 and id<999999;
//执行时间
9999988 rows in set (1.88 sec)
使用了InnoDB存储引擎的表
select * from ti where id>10 and id<999999;
执行时间:
9999988 rows in set (0.65 sec)
有索引查询INNODB有优势
小阿轩-yx存储引擎MyISAM和InnoDB