數據庫做爲存儲數據的倉庫,可能你們會想,關係型數據庫把咱們的數據一行一行地存儲不就完事了嗎?哪裏又冒出個存儲引擎呢?mysql
之因此有多個存儲引擎,是由於咱們對錶的使用場景並不老是相同的,有時候可能咱們須要頻繁的select
和insert
操做,而有的時候可能須要頻繁的update
操做。這個時候,不一樣引擎的數據表table
就有着不一樣的性能了。sql
engine
不一樣,數據庫把數據data
保存至本地的方式(文件的結構)是不同的,物理結構影響着數據的操做。BTree
索引。transaction
操做。目前,只有InnoDB
引擎支持事務操做。須要說明的是,引擎是針對數據表table
而言的,也就是說咱們討論的是一張數據表以何種引擎的方式來進行數據存儲。數據庫
咱們能夠查看MySQL數據庫支持的引擎以及相應的說明。安全
命令:show engines;
工具
在MySQL裏面,咱們主要會使用到的引擎有InnoDB
(默認引擎)、MyISAM
、 MRG_MYISAM
(原名MERGE
) 、MEMORY
。其餘引擎可能非專業DBA
接觸不到,因此接下來的存儲引擎將圍繞上面4個展開。性能
順便說一句,咱們平常絕大部分的都是InnoDB
和MyISAM
引擎。固然,也有一些非官方的引擎,以其高性能而流行,好比說:TokuDB
,它有多項性能指標吊打InnoDB
。spa
table
所使用的引擎命令:rest
show create table userinfo \G; # \G格式化輸出
上面的命令,使用查看建表語句,能夠查看數據表使用的引擎,固然咱們默認的都是InnoDB
。code
命令:對象
create table tb1( ... ... )engine=MyISAM default charset=utf8;
命令:
alter table t1 engine=InnoDB;
特色 | InnoDB | MyISAM | MRG_MYISAM(原MERGE) | MEMORY |
---|---|---|---|---|
存儲大小限制 | 有 | 64TB | 沒有 | 有 |
事務安全 | 支持 | |||
鎖機制 | 行鎖、表鎖 | 表鎖 | 表鎖 | 表鎖 |
BTree索引 | 支持 | 支持 | 支持 | 支持 |
Hash索引 | 支持 | |||
fulltext索引 | 支持 | |||
集羣索引 | 支持 | |||
數據可壓縮 | 支持 | |||
空間使用 | 高 | 低 | ||
內存使用 | 高 | 低 | ||
批量插入的速度 | 高 | |||
支持外鍵 | 支持 |
咱們說過,平常中使用最多的是InnoDB
和MyISAM
引擎,從上表能夠看出,這2者互有長處與短板。所以,咱們要根據業務場景來選擇合適的引擎。
InnoDB
引擎InnoDB
引擎很重要的2項功能(也是獨有)是支持事務 以及支持外鍵 。
事務的重要性不言而喻,金融上重要的轉帳、交易等操做,爲了應對突發事故如停電,須要對數據的操做具備原子性。==事務的具體內容,放置另外一篇章進行講解==。 這裏咱們須要知道,對於涉及到事務的數據表,咱們只能選擇InnoDB
引擎來存儲。
外鍵是一種主從的對應關係。只有InnoDB
支持外鍵foreign key
,下面來說解相關的外鍵操做。
如今假設咱們開了一個書店bookstore
,咱們的書源都是由書籍市場bookmarket
提供,因此咱們的書的bookname
應該做爲一個外鍵,參照bookmarket
的主鍵(bookname
)。
下面咱們來生成上面2個表,並設置相應的主鍵與外鍵。
drop table if exists bookmarket; create table bookmarket( bookname varchar(50), price double, primary key(bookname) ); drop table if exists bookstore; create table bookstore( id int primary key auto_increment, bookname varchar(50), price double, constraint `fk_bookname` foreign key(bookname) references bookmarket(bookname) );
下面咱們來複習如下外鍵相關的知識:
data
中的外鍵列的值必須在主表中存在。換句話說,咱們想要銷售一本新書唐吉坷德
,那麼在bookmarket
中就必須有這本書,咱們是不能銷售沒有貨源的書的。這個操做的名稱很差取,咱們理解仍是很好理解的。在對主表的數據進行CURD
中的刪除和更新時,咱們的從表應該作出哪些相應的操做呢?
咱們能夠選擇的方案有3種:
RESTRICT
或NO ACTION
,這也是未指定時,默認的設置,即on update restrict on delete restrict
。CASCADE
NULL
。SET NULL
咱們如今插入一些相關的數據。
insert bookmarket values('book_1',23.42),('book_2',22.2),('book_3',44.1); insert bookstore values(null,'book_1',30),(null,'book_2',32.2);
而後,咱們以RESTRICT
爲例,先修改從表的外鍵。
alter table bookstore drop foreign key `fk_bookname`; alter table bookstore add constraint `bookstore_fk_bookname` foreign key(bookname) references bookmarket(bookname) on delete restrict on update restrict;
而後,咱們試圖刪除主表的一行數據:
這裏提示,不能刪除數據,由於數據被外鍵所引用。順便一提,默認狀況下,外鍵會採用on delete restrict on update restrict
的方案。
值得一提的是,當咱們使用外鍵的時候,最合理的方式應該是on delete restrict on update cascade
,禁止刪除,更新同步。
有一個小技巧,那就是當咱們導入多個表的數據時,因爲外鍵的存在,咱們導入表的順序就有前後之分。那麼咱們能夠暫時關閉外鍵檢查,這樣就無所謂順序了。
set forign_key_checks=0; ... ... set forign_key_checks=1;
該點水平不夠。
MyISAM
引擎在5.5版本以前,MySQL的默認引擎就是這個,使用的也很普遍。它的優勢在於訪問速度快,適合常常進行select
和insert
操做的場景。缺點就是不支持事務和外鍵。
每一個MyISAM
表在物理上存儲3個文件,分別是:存儲表定義、存儲數據、存儲索引。
適合常常須要進行select
和insert
操做的表。
MyISAM
表支持3種存儲格式,分別是靜態表(默認)、動態表、壓縮表。
咱們建立一個MyISAM
表,有一個列設置爲定長數據。(如char
),注意varchar
是無效的。
drop table if exists isam_t; create table isam_t( id int, name char(12) )engine=myisam charset=utf8;
接下來,咱們插入數據並驗證。
insert isam_t values(2,' tom '),(3,' kim'),(4,' jol '); select id,name,length(name) from isam_t;
咱們能夠看出,name
後面的空格已經被去掉了。
MRG_MYISAM
引擎望文生義,MRG_MYISAM
引擎就是將MyISAM
引擎進行合併。它是一組MyISAM
表的組合。它要求這些表的結構徹底相同,MRG_MYISAM
表自己沒有數據,它只是一個容器,操做的對象仍是內部的MyISAM
表。
很顯然,咱們能夠把它當作是一個分表的工具。前面的引擎對比中,咱們知道MyISAM
表的存儲大小是有限制的,有時候一張表存儲不下全部數據,那麼咱們分紅多張結構徹底相同的表進行分表存儲。這個時候,就是咱們MRG_MYISAM
表的用武之地了。咱們能夠將全部的分表聚合在一塊兒,這樣就可以對全部數據進行操做了。
CURD
操做由於這張表只提供一個容器的功能,因此MRG_MYISAM
表的CURD
操做和傳統意義表的操做是不同的。
create
,定義各個分表的聚合。select
、update
都是操做其內部的分表。delete
只是刪除該表的定義,不影響內部的分表。insert
,須要指定數據插入的表,insert_method
的可選值只能是first
和last
和no
,no
表示不能執行插入操做,默認也是no
。咱們先生成2張MyISAM
表,而後生成一個MRG_MYISAM
表,包含前面2個分表。這裏咱們指定insert_method
爲last
。
drop table if exists bill_2016; create table bill_2016( id int primary key, time date, cost double )engine=myisam; drop table if exists bill_2017; create table bill_2017( id int primary key, time date, cost double )engine=myisam; drop table if exists bill_merge; create table bill_merge( id int primary key, time date, cost double )engine=merge union=(bill_2016,bill_2017) insert_method=last;
而後咱們往2張分表中插入數據。
insert bill_2016 values(1,'2016-1-2',22.4),(2,'2016-2-3',44.2); insert bill_2017 values(100,'2017-4-2',55.2),(102,'2017-6-3',88); select * from bill_2016; select * from bill_2017;
咱們查看MRG_MYISAM
表的數據。
能夠發現,bill_merge
包含了2個分表的數據。
這時候咱們向bill_merge
插入數據,按照預期,數據應該被插入了第2張表,也就是bill_2017
中。
MRG_MYISAM
表在物理上生成2個文件,其一是存儲表定義,其二是包含組合表的信息和插入依據。
MEMORY
引擎MEMORY
引擎使用內存中的數據來建立表,在物理上只對應一個文件。MEMORY
表的訪問速度很是快,由於它的數據是放在內存中的,若是服務一旦關掉,那麼表中的數據就會丟失。
主要用於存儲內容變化不頻繁的代碼表,或者是做爲統計操做的中間結果表。相似於一箇中間數據存儲站,提供給其餘操做進行查詢。須要注意的是,該表的數據並不會寫入磁盤,因此數據的保存須要注意。
咱們使用bookmarket
表的數據,來生成咱們的MEMORY
表。
create table emp_memory engine=memory select * from bookmarket;
咱們在生成索引的時候,能夠選擇Hash
或者BTree
這2種。
create index idx_bookname using hash on emp_memory(bookname); show index from emp_memory;
當咱們不須要MEMORY
表的時候,咱們應該刪除從而釋放內存。
能夠是delete from
、truncate table
、drop table
等。