1. 程式人生 > >7.Mysql存儲引擎

7.Mysql存儲引擎

如何選擇 merge存儲引擎 配置文件 %d 2.3 種類型 myisam gin 選擇

7.表類型(存儲引擎)的選擇
7.1 Mysql存儲引擎概述
mysql支持插件式存儲引擎,即存儲引擎以插件形式存在於mysql庫中。
mysql支持的存儲引擎包括:MyISAM、InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED等。
其中:InnoDB和BDB提供事務安全表,其他存儲引擎都是非事務安全表;
默認存儲引擎(即建表時不指定存儲引擎),mysql5.5開始默認存儲引擎為InnoDB,mysql5.5之前默認存儲引擎為MyISAM。
1.查看默認存儲引擎:InnoDB
select @@default_storage_engine;

show variables like ‘default_storage_engine‘;
修改默認存儲引擎,在配置文件(mysql.cnf)中修改參數default_storage_engine。
2.查看當前mysql支持的存儲引擎
show engines;
select * from information_schema.ENGINES;
show variables like ‘have%‘;
3.建表時通過engine關鍵字設置表的存儲引擎
create table test1(id bigint(20) not null auto_increment,primary key(id)) engine=Innodb/myisam default charset=gbk/utf8;
4.修改現有表的存儲引擎
alter table test1 engine=Innodb/myisam;
show create table test1;

7.2 各種存儲引擎的特性
常用存儲引擎對比:
特點 MyISAM InnoDB MEMORY MERGE NDB
存儲限制 有 64TB 有 沒有 有
事務安全 -- 支持 -- -- --
鎖機制 表鎖 行鎖 表鎖 表鎖 行鎖
B樹索引 支持 支持 支持 支持 支持

哈希索引 -- -- 支持 -- 支持
全文索引 支持 -- -- -- --
集群索引 -- 支持 -- -- --
數據緩存 -- 支持 支持 -- 支持
索引緩存 支持 支持 支持 支持 支持
數據可壓縮 支持 -- -- -- --
空間使用 低 高 N/A 低 低
內存使用 低 高 中等 低 高
批量插入速度 高 低 高 高 高
支持外鍵 -- 支持 -- -- --
7.2.1 MyISAM
MyISAM不支持事務、不支持外鍵,訪問速度快,適用於不要求數據完整性或以Select和Insert為主的應用系統。
1.MyISAM表存儲
MyISAM表在磁盤上存儲為3個文件,文件名都與表名相同,擴展名分別為:
.frm(存儲表定義)
.MYD(存儲表數據,MyISAM data)
.MYI(存儲表的索引數據,MyISAM Index)。
數據文件和索引文件可以放置在不同的目錄,以平均分布IO提升性能;
在建表時通過DATA DIRECTORY和INDEX DIRECTORY指定數據文件和索引文件的存放路徑(絕對路徑)即可。
MySQL創建表默認在放在datadir路徑下,當datadir空間不足時,可再建表時指定DATA DIRECTORY、INDEX DIRECTORY將新表數據存在其他磁盤例如:/data/lottery/;
註意:
INNODB 表要是獨立表空間(innodb_file_per_table=1)。
目前只有5.6後才支持單表指定目錄,且目錄是mysql:mysql。
在Windows中將忽略DATA DIRECTORY和INDEX DIRECTORY選項
DATA/INDEX DIRECTORY不支持開啟skip-symbolic-links參數;http://www.51edu.com/it/bckf/117508.html
普通表 DATA/INDEX DIRECTORY只在建表時指定,不可以alter table更改;
分區表可alter add PARTITIONS data DIRECTORY....
查看mysql數據文件存放路徑
show global variables like "%datadir%";
‘datadir‘, ‘C:\\Program Files\\MySQL\\Data\\Data\\‘

例子:
drop table test1;
create table test1(id bigint(20) not null auto_increment,primary key(id))
engine=myisam default charset=gbk INDEX DIRECTORY=‘C:\\‘;

2.MyISAM表損壞
因各種原因,MyISAM表可能會損壞。
可以用check table來檢查MyISAM表是否損壞;
並用repair table來修復損壞的MyISAM表。
例子:
check table test1;
repair table test1;

3.MyISAM表存儲格式類型
MyISAM表支持3種類型的存儲格式:
靜態(固定長度)表:默認的存儲格式,列全部采用非變長類型,每條記錄使用固定的長度,長度不足時使用空格補齊,返回時不帶尾部空格。
優點:存儲快速、容易緩存、容易故障恢復;
缺點:占用空間多,數據尾部空格丟失。
動態表:包含變長類型字段,記錄長度不固定,優點占用空間小,缺點頻繁的更新和刪除記錄將產生磁盤空間碎片,
且mysql不會自動合並磁盤空間碎片(Oracle通過pct free和pct used參數控制,當插入數據空間需求小於總的可用空間,且任何一塊可用空間又不插入數據空間需求時,Oracle將自動合並空間碎片),
需要手動定期執行optimize table語句或者myisamchk -r 命令來改善性能,並且故障恢復比較困難。
壓縮表:由myisampack工具創建,占用空間小,每條記錄被單獨壓縮。

7.2.2 InnoDB
InnoDB提供了具有提交、回滾和崩潰恢復能力的事務安全,寫效率較差,占用空間多。
1.自動增長列
drop table test1;
create table test1(id bigint(20) not null auto_increment,name varchar(10),primary key(id));
關鍵字auto_increment,從1開始每次增加1,每個表只能有一個自增列,一般作為主鍵列使用
插入數據時,正常情況下,不要插入自增列;
insert into test1 (name) values (‘a‘),(‘b‘);
也可以為了省略列名而給自增列插入0或null,自增列會根據當前值加1;
insert into test1 values (0,‘c‘),(null,‘d‘);
如果給自增列手動插入比當前序號大的值,將會導致自增序號發生變更,並且後續記錄將以插入值作為起始值;
insert into test1 values (6,‘e‘),(0,‘e2‘),(18,‘f‘),(null,‘f2‘);
如果給自增列手動插入與現有值相同的值,將會導致報錯。
insert into test1 values (1,‘a2‘),(6,‘e2‘); -- 1062
查看上次操作的序號,如果上次操作是批量操作時,則是第一條記錄的插入序號:
select last_insert_id();
修改當前序號:
alter table test1 auto_increment=30; -- 註意:該起始序號值保存在內存中,重啟服務會丟失。
show create table test1;
select last_insert_id();
insert into test1 (name) values (‘a‘);
select * from test1;
註意:
對Innodb引擎表,自動增長列必須是索引列,如果是組合索引時,也必須是組合索引的第一列。
對Myisam引擎表,自動增長列也必須是索引列,如果是組合索引時,可以是組合索引的非第一列,
此時自動增長列按照組合索引的前幾列排序後再自增(當前幾列與已有記錄不重時,自增列為1,否則自增列加1)。
例子:
drop table test1;
create table test1(id bigint(20) not null auto_increment,name varchar(10),index(name,id)) engine=Myisam;
insert into test1 (name) values (‘a‘),(‘b‘);
select * from test1;
insert into test1 (name) values (‘a‘),(‘b‘);
select * from test1;

2.外鍵約束
mysql中只有innodb引擎支持外鍵,
外鍵要求兩張表有相同的列,並且該相同列在其中一張表為主鍵,稱這張表為父表,
在另一張為非主鍵,稱這張表為子表,外鍵用於表示父表到子表的一對多關系。
在mysql中為子表創建外鍵,系統會為外鍵列自動添加索引(oracle中不會自動添加外鍵索引)。
例子:
use scott;
create table dept1(
deptno int not null auto_increment,
dname varchar(100),
last_update timestamp,
primary key (deptno)
) engine=innodb default charset=utf8;
create table emp1(
empno int not null auto_increment,
ename varchar(100),
birth_date date,
deptno int,
primary key (empno),
key idx_fk_emp_deptno(deptno),
constraint fk_emp_deptno foreign key (deptno) references dept1(deptno) on delete restrict on update cascade
) engine=innodb default charset=utf8;
在創建外鍵約束時可以指定對父表進行更新、刪除時子表的級聯動作,分為以下4種:
restrict 限制:當子表相關記錄存在時,不允許更新、刪除父表;
cascade 級聯:當更新、刪除父表記錄時,同時更新、刪除子表記錄;
set null 設置為空:當更新、刪除父表記錄時,將子表記錄設置為null;
no action 不處理:當更新、刪除父表記錄時,不處理子表相應記錄。
註意:父表的主鍵或主鍵列索引禁止被刪除。alter table dept1 drop primary key; -- 1075 自增列必須定義為key(主鍵或索引)
關閉外鍵約束:set foreign_key_checks=0;
啟用外鍵約束:set foreign_key_checks=1;

3.存儲方式
InnoDB存儲方式分兩種:共享表空間存儲、多表空間存儲。
共享表空間存儲:表結構保存在.frm文件中,數據和索引保存在innodb_data_home_dir和innodb_data_file_path定義的表空間中,可以是多個文件。
C:\Program Files\MySQL\Data\Data\ibdata1
多表空間存儲: 表結構保存在.frm文件中,數據和索引保單獨存在“表名.ibd”文件中(每個表一個.ibd文件)。對於分區表每個分區一個“表名+分區名.ibd”文件,不同分區的文件可以有不同的存儲路徑以均衡IO;
多表空間的數據文件沒有大小限制,不需要設置初始大小,不需要設置文件的最大限制,擴展大小等參數。
C:\Program Files\MySQL\Data\Data\scott\dept.frm
C:\Program Files\MySQL\Data\Data\scott\dept.ibd
相關參數:
select @@innodb_data_home_dir; -- null
select @@innodb_data_file_path; -- ibdata1:12M:autoextend
select @@innodb_file_per_table; -- 1 啟用多表空間(0 不啟用多表空間)
一般情況下,共享表空間用於存儲InnoDB內部數據字典和在線重做日誌;在設置了參數innodb_file_per_table=1時,多表空間用於存儲自定義的表。
改變參數innodb_file_per_table的設置(需要修改參數文件並重啟服務),即切換共享表空間和多表空間存儲方式,不會影響之前已經定義表的存儲方式,只影響新建表的存儲方式。
對於使用多表空間特性的表,直接復制.frm文件和.ibd文件進行備份後,不能恢復到其他mysql數據庫(因為沒有共享表空間的數據字典信息);
給本地mysql恢復時需要使用一下命令:
alter table tbl_name discard tablespace;
alter table tbl_name import tablespace;

7.2.3 MEMORY
MEMORY存儲引擎用於在內存中建表。
MEMORY表只有一個表結構.frm文件,數據存放在內存中,並默認使用HASH索引,服務關閉數據丟失(數據不做持久化)。
例子:
-- 創建memory表,在C:\Program Files\MySQL\Data\Data\scott\下只有一個表結構文件emp_memory.frm
create table emp_memory engine=memory select * from emp;
-- 查詢memory表,數據在內存中,所以訪問速度快
select * from emp_memory;
-- 查看memory表狀態
show table status like ‘emp_memory‘;
-- 給memory表創建索引,索引類型支持hash和btree
create index men_hash using hash on emp_memory(empno);
create index men_btree using btree on emp_memory(ename);
-- 查看索引
show index from emp_memory;
-- 刪除索引
drop index men_hash on emp_memory;
在啟動MySQL服務時使用--init-file選項加載初始化文件,在該文件中創建memory表或者為memory表加載數據,即可解決重啟服務memory表數據丟失的問題。
-- 釋放memory表占用的內存,可以選擇執行delete語句、truncate table語句、drop table語句
set sql_safe_updates=0;
delete from emp_memory; -- 刪除數據
insert into emp_memory select * from emp; -- 加載數據
truncate table emp_memory; -- 截斷數據(清空表)
drop table emp_memory; -- 刪除表
memory表的數據量受參數max_heap_table_size的控制,默認16MB,可以根據需要調整。
-- 查看參數設置
select @@max_heap_table_size; -- ‘16777216‘
-- 修改參數設置
set max_heap_table_size=33554432; -- 調整為32MB
-- 在創建memory表時指定行數max_rows
create table emp_memory engine=memory max_rows=10 select * from emp;
memory存儲引擎適用於內容變化不頻繁的代碼表,或者統計操作的中間結果表。
memory表適用於快速查詢,對memory表的增刪改操作都不會被持久化。

7.2.4 MERGE
MERGE表是一組同構MyISAM表的邏輯組合,MERGE表不存儲數據,數據在一組同構MyISAM表中的一個表中存儲。
對MERGE表的增刪改查操作,實際是對一組同構MyISAM表做增刪改查操作。
MERGE表包含兩個物理文件,.frm文件用來保存MERGE表定義,.MRG文件包含MERGE表和一組同構MyISAM表的映射關系,及插入數據時的依據。
create、alter、drop MERGE表,只會修改MERGE表的.frm文件文件,不會影響一組同構MyISAM表及數據。
可以自行修改.MRG文件,修改後需要使用flush tables命令來刷下表。
例子:
-- 創建兩個同構的MyISAM表
create table sale_order_2017(id int not null auto_increment,sal_date date,sal_name varchar(100),primary key (id)) engine=myisam;
create table sale_order_2018(id int not null auto_increment,sal_date date,sal_name varchar(100),primary key (id)) engine=myisam;
-- 創建MERGE表
create table sale_order_merge(id int not null auto_increment,sal_date date,sal_name varchar(100),primary key (id)) engine=merge union=(sale_order_2017,sale_order_2018) insert_method=last;
MERGE表和一組同構MyISAM表的映射關系:union=(sale_order_2017,sale_order_2018)
插入數據時的依據insert_method分為first\last\no\缺省,first指插入到第一張表,last指插入到最後一張表,no和缺省指不允許插入操作。
-- 給兩個同構的MyISAM表分別插入數據
insert into sale_order_2017 values (null,‘2017-1-1‘,‘abc‘);
insert into sale_order_2017 values (null,‘2017-2-1‘,‘abcd‘);
insert into sale_order_2018 values (null,‘2018-1-1‘,‘abc‘);
insert into sale_order_2018 values (null,‘2018-2-1‘,‘abcd‘);
-- 查看MERGE表
select * from sale_order_merge;
-- 給MERGE表插入數據
insert into sale_order_merge values (null,‘2017-12-1‘,‘abcde‘);
-- 查看MERGE表和兩個同構的MyISAM表
select * from sale_order_merge;
select * from sale_order_2017;
select * from sale_order_2018; -- 發現給meger表插入的數據由於指定了insert_method=last被插入到第二張表中,而不是根據日期值按範圍分區。
鑒於MERGE表的插入只能指定first或last(而分區表則可以根據分區鍵自動選擇分區),其功能性已被分區表所取代。

7.2.5 TokuDB
TokuDB是一個高寫性能、支持事務處理的MySQL和MariaDB的第三方存儲引擎,具有高擴展性、高壓縮率、高效的寫入性能、支持在線DDL操作。
特點:
使用Fractal樹索引,保證高效的插入性能;
優秀的壓縮特性,比InnoDB高近10倍;
Hot Schema Changes特性支持在線創建索引、添加刪除屬性列等DDL操作;
使用Bulk Loader快速加載大量數據;
提供主從延遲消除技術;
支持ACID和MVCC。
適用場景:
日誌數據
歷史數據
在線DDL較頻繁的場景。

7.3 如何選擇合適的存儲引擎
MyISAM存儲引擎適用於以讀取操作和插入操作為主的系統(少量更新和刪除操作),並且對事務的完整性、並發性要求不高,一般用於數據倉庫類型的系統中。
MERGE存儲引擎用於將一系列相同的MyISAM表以邏輯方式組合在一起,並作為一個對象引用它們,用於突破MyISAM單表的大小限制,並分布在多個磁盤,以均衡IO(以邏輯分區整合MyISAM表),一般用於數據倉庫類型的系統中。
InnoDB存儲引擎用於事務處理型系統,支持外鍵,支持事務完整性,支持行鎖。
MEMORY存儲引擎用於在內存中建表,以提升訪問速度。無法在內存中加載大量數據,不可恢復,不支持頻繁更新。

7.4 小結

7.Mysql存儲引擎