MySQL存储引擎
前言
MySQL不同于其他数据库,它有存储引擎这个概念,可以让我们灵活地在实际存储环境中采用最优的存储引擎,最常用的引擎是InnoDB与MyISAM,本文的介绍也是主要针对这两个进行介绍!
主要参考资料《深入浅出MySQL》(有需要的可以私信/评论我,发电子高清PDF版给你)
一、存储引擎的选择
(1)输入命令show engines查看当前数据库支持的存储引擎:可以看到该数据库默认的引擎InnoDB,也可以看到引擎的相关简单特点介绍
mysql> show engines; +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 9 rows in set
(2)输入命令SHOW VARIABLES LIKE '%storage_engine'查看数据库默认使用的哪个引擎(如果为空则试试SHOW VARIABLES LIKE '%storage_engine%')
mysql> show variables like '%storage_engine'; +----------------------------------+--------+ | Variable_name | Value | +----------------------------------+--------+ | default_storage_engine | InnoDB | | default_tmp_storage_engine | InnoDB | | internal_tmp_disk_storage_engine | InnoDB | +----------------------------------+--------+ 3 rows in set
(3)在创建表的时候,可以使用命令:CREATE TABLE table_name(...)ENGINE = InnoDB/MyISAM DEFAULT CHARSET=gbk即可指定数据库引擎
(4)可以使用show create table table_name语句查看表的SQL创建语句,即可以看到该表使用的引擎。
(5)执行命令ALTER TABLE tablename engine = InnoDB改变表的引擎
二、存储引擎的特点
1.InnoDB引擎
1.1 特点分析
(1)InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。相比较MyISAM存储引擎,InnoDB写的处理效率差一点并且会占用更多的磁盘空间保留数据和索引。
(2)提供了对数据库ACID(原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability)事务的支持,实现了SQL标准的四种隔离级别;
(3)设计目标就是处理大容量的数据库系统,MySQL运行时InnoDB会在内存中建立缓冲池,用于缓冲数据和索引。
(4)执行“select count(*) from table”语句时需要扫描全表,只是因为InnoDB不会像MyISAM那样不保存具体的行数,所以需要扫描整个表才能计算多少行。
(5)由于是行锁,粒度更小,所以写操作不会锁定全表,在并发较高时,使用InnoDB会提升效率。即存在大量UPDATE/INSERT操作时,效率较高。
(6)InnoDB不支持FULLTEXT类型的索引,即不支持全文索引
(7)InnoDB清空数据量大的表时,是非常缓慢,这是因为InnoDB必须处理表中的每一行,根据InnoDB的事务设计原则,首先需要把“删除动作”写入“事务日志”,然后写入实际的表。所以,清空大表的时候,最好直接drop table然后重建。即InnoDB一行一行删除,不会重建表。
1.2 使用场景
(1)经常UPDETE/INSERT的表,使用处理多重并发的更新请求
(2)支持事务,必选InnoDB
(3)可以从灾难中恢复(日志+事务回滚)
(4)外键约束、列属性AUTO_INCREMENT支持
1.3 不同于其他引擎的特点介绍:
(1)自动增长列:
1) 自动增长的列可以手工插入,但是如果插入的为null或者0,则实际的是自增后的值。
2) 使用ALTER TABLE tablename AUTO_INCREMENT = initial_value强制设置列增长的初始值,默认为1。但是该initial_value值是保存在内存中的,如果使用该值之前数据库重启启动的话,这个强制的默认值会丢失,就会需要重新设置。
3) 执行select LAST_INSERT_ID()可以查看当前线程最后插入记录使用的值,但是一次插入好多条记录的话,那么返回的是第一条的自增值。即insert tablename values(1),(2),(3)则返回的是value(1)的自增值。
4) InnoDB自增列必须是索引(主键是一种聚集索引),如果是组合索引,也必须是组合索引的第一列。而MyISAM可以是组合索引的其他列(按照组合索引的前面几列进行排序后递增的),即index(col1,col2)中自增列为col1
(2)外键约束:
1) MySQL唯一支持外键的只有InnoDB,创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引。
2) 在创建索引的时候,可以指定在删除、更新父表的时候,对子表进行相应的操作,如:RESTRICT、CASCADE、SET NULL、NO ACTION(与RESTRICT相同)
RESTRICT:限制子表有关联记录的情况下父表不能更新。
CASCADE:父表在更新或删除的时候,更新/删除子表对应记录。
SET NULL:父表在更新或者删除的时候,子表对应字段SET NULL
比如:子表中外键指定时候有ON DELETE RESTRICT ON UPDATE CASCADE,表明在父表删除的时候,子表有对应记录不允许被删除,主表在更新记录的时候,子表如果有对应记录则子表对应更新。
CONSTRAINT fk_student_course FOREIGN KEY(student_id) REFERENCES student(student_id) ON DELETE RESTRICT ON UPDATE CASCADE;
3) 当某个表被其他表创建了参考外键,那么该表对应的索引或者主键禁止被删除。如果操作LOAD DATA与ALTER TABLE需要暂时关闭外键检查可以加快处理速度,执行SET FOREIGN_KEY_CHECKS=0关闭,之后执行SET FOREIGN_KEY_CHECKS=1恢复原状。通过命令可以查看index与keys
mysql> show index from user; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | user | 0 | PRIMARY | 1 | id | A | 3 | NULL | NULL | | BTREE | | | | user | 0 | PRIMARY | 2 | major_id | A | 3 | NULL | NULL | | BTREE | | | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 2 rows in set mysql> show keys from user; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | user | 0 | PRIMARY | 1 | id | A | 3 | NULL | NULL | | BTREE | | | | user | 0 | PRIMARY | 2 | major_id | A | 3 | NULL | NULL | | BTREE | | | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 2 rows in set
(3)存储格式
InnoDB存储表和索引主要有两种方式,一是共享表空间存储,二是使用多表(单独)空间存储。
1) 使用共享表空间存储:表与表结构保存在.frm文件中(事实上与引擎无关),数据和索引保存在innodb_data_home_dir和innodb_data_file_path表空间中,可以是多个文件。是MySQL默认的存储方式。
a. 使用命令:show variables like 'innodb_data%'即可查看:
mysql> show variables like 'innodb_data%'; +-----------------------+------------------------+ | Variable_name | Value | +-----------------------+------------------------+ | innodb_data_file_path | ibdata1:12M:autoextend | | innodb_data_home_dir | | +-----------------------+------------------------+ 2 rows in set
默认的表空间为ibdata1,初始值为12M;
b. 表空间可以由多个文件组成,所以其大小限制不是文件大小的限制,而是其自身的限制
2) 使用多表(单独)空间存储:
a. 表与表结构在.frm文件中(事实上有引擎无关),但是每个表的数据与索引单独保存在.ibd中,如果是分区表那么对应单独的“表明+分区名”为文件名的.ibd文件;
b. 多表空间参数innbdb_file_per_table=ON生效后,只对新建的表生效;
c. 多表空间数据文件没有大小限制,不需要设置初始大小,也不需要设置文件的最大限制,扩展参数等。
d. 使用多表空间特性的表,可以方便进行单表备份与恢复,但是直接复制.ibd文件是不可行,因为没有共享表空间的数据字典信息,字节复制.ibd文件和.frm文件是不能正确识别的。
e. 即便是在多表空间在存储方式下,共享表空间仍然是必须的,这是因为InnoDB把内部数据词典和日志放在这个文件里。
注:我一开始理解记忆的时候经常晕,这里如果才接触的话可以记个大概即可,之后感兴趣特别是对MySQL管理部分中的物理备份(通过对文件的cp)就可能会使用到这里的知识。
2.MyISAM引擎
2.1 特点分析
(1)MyISAM不支持事务,不支持外键,SELECT/INSERT为主的应用可以使用该引擎。
(2)每个MyISAM在存储成3个文件,扩展名分别是:
① .frm:存储表定义(表结构等信息)
②.MYD(MYData),存储数据
③.MYI(MYIndex),存储索引
(3)指定索引文件和数据文件的路径,需要在创建表的时候通过DAT DIRECTORY和INDEX DIRECTORY语句指定,也就是说不同MyISAM表的索引文件和数据文件可以放置到不同的路径下。
(4)MyISAM类型的表提供修复的工具,可以用CHECK TABLE语句来检查MyISAM表健康,并用REPAIR TABLE语句修复一个损坏的MyISAM表。
(5)只有MyISAM支持FULLTEXT全文索引
2.2 存储格式
MyISAM的表支持3种不同的存储格式,分别为:静态表(默认的)、动态表、压缩表。
(1)静态表:表中字段都是非变长字段,每个记录都是固定长度,当表不包含可变长度列(VARCHAR,BLOB,TEXT)使用。
① 优点:存储迅速,容易缓存,出现故障容易恢复
② 缺点:占用的空间通常比动态表多,这是因为静态表中数据存储的时候会根据列宽度补足空格,但是访问的时候是不可见的(真实数据存在的空格也会被去掉)
(2)动态表:表中包含变长字段,记录是不固定长度的。当表包含可变长度列(VARCHAR,BLOB,TEXTDynamic),或者一个表被用ROW_FORMAT=DYNAMIC选项创建时候使用。
① 优点:占用空间相对较少
② 缺点:频繁更新/删除记录会产生碎片,需要定期执行OPTIMIZE TABLE tablename或myisamchk -r命令改善性能;出现故障恢复相对比较困难。
(3)压缩表:是由myisampack工具创建的,占用非常小的磁盘空间,因为每个记录都会被单独压缩,所以只有非常小的方位开支。
总结与补充
(1)以上主要是从MySQL存储引擎的使用场景、存储格式等方面介绍,在实际环境中选择利用好存储引擎可以达到事半功倍的效果;
(2)当我们需要进行一些操作的时候需要额外考虑使用的存储引擎是否支持,比如你在对MyISAM的表建立外键约束是不会报错的,也不会提示的;
(3)当然,InnoDB与MyISAM两种常用存储引擎可以混合使用,对并发量高的情况下、需要事务恢复等情况的表可以使用InnoDB,对SELECT/INSERT频繁的表可以使用使用MyISAM。