MySQL主流存儲引擎概述

MySQL常用的存儲引擎爲MyISAM、InnoDB、MEMORY、MERGE,其中InnoDB提供事務安全表,其他存儲引擎都是非事務安全表。 

MyISAM是MySQL的默認存儲引擎。MyISAM不支持事務、也不支持外鍵,但其訪問速度快,對事務完整性沒有要求。 

InnoDB存儲引擎提供了具有提交、回滾和崩潰恢復能力的事務安全。但是比起MyISAM存儲引擎,InnoDB寫的處理效率差一些並且會佔用更多的磁盤空間以保留數據和索引。 

MEMORY存儲引擎使用存在內存中的內容來創建表。每個MEMORY表只實際對應一個磁盤文件。MEMORY類型的表訪問非常得快,因爲它的數據是放在內存中的,並且默認使用HASH索引。但是一旦服務關閉,表中的數據就會丟失掉。其次它有空間大小的限制。

MERGE存儲引擎是一組MyISAM表的組合,這些MyISAM表必須結構完全相同。MERGE表本身沒有數據,對MERGE類型的表進行查詢、更新、刪除的操作,就是對內部的MyISAM表進行的。


它們間的特點關係對比

MyISAM

Myisam是Mysql的默認存儲引擎,當create創建新表時,未指定新表的存儲引擎時,默認使用Myisam。
每個MyISAM在磁盤上存儲成三個文件。文件名都和表名相同,擴展名分別是.frm(存儲表定義)、.MYD (MYData,存儲數據)、.MYI (MYIndex,存儲索引)。數據文件和索引文件可以放置在不同的目錄,平均分佈io,獲得更快的速度。   

要指定索引和數據文件的路徑,需要在創建表時通過'data directory'和'index dircetory'語句來指定,即它們可以放置在不同的路徑下,當然要給出其絕對路徑且還要有相應的權限。

造成myisam類型表損壞的原因有多種,且損壞後表就不能再被訪問了,會提示錯誤的結束或要求修正或異常重啓。解決的方法有:使用'check table'來檢查myisam表,'repair table'可用來修復一個受損的myisam表。

MyISAM表還支持3中不同的存儲格式: 
1、靜態表
2、動態表
3、壓縮表

靜態表是默認的存儲格式,靜態表中的字段都是非變長的字段,優點是:存儲非常迅速,容易緩存,出現故障容易恢復;缺點是:佔用的空間通常比動態表多。(注意: 在存儲時,列的寬度不足時,用空格補足,在返回給應用時並不會將這些空格也給應用;同理當字段後本來有空格時,數據庫也會自動處理掉它,但字段前的空格將會保留)
 
動態表的字段是變長的,優點是:佔用的空間相對較少,但是頻繁地更新刪除記錄會產生碎片,需要定期改善性能(optimize table或myisamchk -r命令),並且出現故障的時候恢復相對比較困難。 

壓縮表佔用磁盤空間小,每個記錄是被單獨壓縮的,所以只有非常小的訪問開支且爲只讀。

如果你的應用是不需要事務,處理的只是基本的CRUD操作,那麼MyISAM是不二選擇。

在myisam表中,自增列可以是組合索引的其它列,當插入記錄後,自增列是按組合索引的前幾列進行排序後遞增的。

InnoDB
InnoDB存儲引擎提供了具有提交、回滾和崩潰恢復能力的事務安全。但是對比Myisam的存儲引擎,InnoDB寫的處理效率差一些並且會佔用更多的磁盤空間以保留數據和索引。支持外鍵存儲引擎只有InnoDB,在創建外鍵的時候,要求附表必須有對應的索引,子表在創建外鍵的時候也會自動創建對應的索引。 
InnoDB存儲方式爲兩種:
1、使用共享表空間存儲,這種方式創建的表的結構保存在'.frm'文件中,數據和索引保存在innodb_data_home_dir和innodb_data_file_path定義的表空間中,可以是多個文件。
2、使用多表空間,這種方式創建的表結構仍然保存在'.frm'文件中,但數據和索引單獨保存中'.ibd'文件中。如果是分區表,則每個分區對應單獨的'.ibd'文件,文件名是“表名+分區名”,可以在創建分區時指定每個分區的數據文件位置,以此來將i/o分佈在多個磁盤上。要使用多表空間方式,需要設置參數:innodb_file_per_table,並重啓服務生效,新建表將新的方式來創建,已有的表仍會使用共享表空間方式存儲。如果將已有的多表空間方式改回爲共享表方式,則新建表會在共享表空間中創建,但已經有的多表空間依然保持原有的訪問方式。所以表空間參數生效後,只對新建的表有效。

多表空間方式的數據文件沒有大小限制,無需初始其大小,也不需要設置文件最大限制、擴展大小等參數。對於多表空間表,可以比較方便地進行單表備份和恢復,但直接複製'.ibd'文件是不行的,因爲沒有提供其數據字典信息,直接複製'.ibd'與'.frm'文件恢復時是不能被正確識別的,要通過下面指令來操作:
alter table tbl_x discard tablespace;
alter table tbl_x import tablespace;

即可將備份恢復到數據庫中,但這種的單表備份,只能恢復到原表所在的數據庫中,而不能恢復到其它庫中,當然這需要使用'mysqldump'或'mysqlimport'工具來實現。

注意:即使在多表空間模式下,共享表空間是必須的,因此innodb將內部數據詞典和未完成日誌存放於此。

當對auto_increment列插入空、'0'、'null'時,它都將自動轉換爲合適且正確值。

當使用'last_insert_id()'查詢當前線程最後插入記錄使用值,若一次插入了多條記錄,則它返回的是第一條記錄所使用的自增值。

對於innodb表,自動增長列必須是索引,如果是組合索引,也必須是其的第一列,這個與myisam是有區別的。

InnoDB被設計成適用於高併發讀寫的情況.使用MVCC(Multi-Version Concurrency Control)以及行級鎖來提供遵從ACID的事務支持。InnoDB支持外鍵參照完整性,具備故障恢復能力。另外 InnoDB的性能其實還是不錯的,特別是在處理大數據量的情況下,用官方的話說就是: InnoDB的CPU效率是其他基於磁盤的關係數據庫存儲引擎所不能比的。不過InnoDB的備份恢復要麻煩一點,除非你使用了4.1以後版本提供的Mulit-tablespace支持,因爲InnoDB和MyISAM不同,他的數據文件並不是獨立對應於每張表的。而是使用的共享表空間,簡單的拷貝覆蓋方法對他不適用,必須在停掉MYSQL後對進行數據恢復。使用Per-Table Tablespacesd,使其每張表對應一個獨立的表空間文件,則情況要簡單很多。

在指定外鍵約束時,可以指定在刪除、更新父表時,對子表進行相應操作,包括:restrict、cascade、set null、no action。其中restrict與no action相同,即限制在子表有關聯記錄的情況下父表不能更新;cascade表示父表在更新或刪除時,更新或刪除子表對應的記錄;set null則表示父表在更新或刪除時,更新或刪除子表對應的字段被set null。所以選擇後兩種方式要謹慎,可能會因此錯誤的操作導致數據丟失。

當某表被其它表創建了外鍵參照,那麼該表的對應索引或主鍵禁止被刪除。

mysql> create table menu(id smallint not null auto_increment primary key,alias char(16) not null,descri varchar(256))engine=InnoDB;
mysql> insert into menu values('','news','about all news');
mysql> insert into menu values('null','product','in open source product variety');

mysql>create table article(id int not null auto_increment,pid smallint not null,keywords varchar(256),intro tinytext,last_update timestamp default 0 on update current_timestamp,primary key(id),key idx_art_menu(pid),constraint foreign key (pid) references menu(id) on delete restrict on update cascade)engine=innodb;

constraint 後最好跟一直觀別名,來描述此外鍵約束。

mysql> insert into article values('',1,'mysql key words','none of none','');
Query OK, 1 row affected, 2 warnings (0.00 sec)

mysql> show warnings;
+---------+------+------------------------------------------------------+
| Level   | Code | Message                                              |
+---------+------+------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: '' for column 'id' at row 1 |
| Warning | 1265 | Data truncated for column 'last_update' at row 1     |
+---------+------+------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> select * from article;
+----+-----+-----------------+--------------+---------------------+
| id | pid | keywords        | intro        | last_update         |
+----+-----+-----------------+--------------+---------------------+
|  1 |   1 | mysql key words | none of none | 0000-00-00 00:00:00 |
+----+-----+-----------------+--------------+---------------------+

mysql> insert into article values('null',2,'free oa office','intro text here',now());

mysql> insert into article values('null',3,'mysql storeage engine ','may be lots of it',now());
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`article`, CONSTRAINT `article_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `menu` (`id`) ON UPDATE CASCADE)

mysql> delete from menu where id=2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`article`, CONSTRAINT `article_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `menu` (`id`) ON UPDATE CASCADE)

在導入多個表的數據時,如果需要忽略表之前的導入順序,可以暫時關閉外鍵的檢查;同理,在執行load data 和 alter table操作的時候,可以通過暫時關閉外鍵約束來加快處理速度,指令是:"set foreign_key_checks=0;",在處理完成後,通過"set foreign_key_checks=1;"來複原。

MEMORY

MEMORY類型的存儲引擎主要用於那些內容變化不頻繁的代碼表,或者作爲統計操作的中間結果表,便於高效地堆中間結果進行分析並得到最終的統計結果。對MEMORY存儲引擎的表進行更新操作要謹慎,因爲數據並沒有實際寫入到磁盤中,所以一定要對下次重新啓動服務後如何獲得這些修改後的數據有所考慮。 此類表實際僅對應一個磁盤文件:.frm,默認使用hash索引。

mysql>create table arts engine=memory select id,alias,title,hits from freeoadb.content;
mysql> show table status like 'corps';

每個memory有所能放置的數據量,受到max_heap_table_size系統變量約束,初始值爲16MB,可以按需加大;另外在其定義時,可以通過max_rows來指定表的最大行數。服務器需要充足的內存來維持這些表,當不需要這些表及內容時,清空(delete from 或 truncate)它們可以釋放內存。
當數據量過大時,就會報出下面的問題,而導致建表失敗:
ERROR 1114 (HY000): The table 'arts' is full

此種類型表有許多自身不足,從而限制了其用途。大小限制、字段類型限制、無持久性。查詢速度快,可用其做一些中間結果暫存表之用。

Merge

MERGE用於將一系列等同的MyISAM表以邏輯方式組合在一起,並作爲一個對象引用它。MERGE表的優點在於可以突破對單個MyISAM表大小的限制,通過將不同的表分佈在多個磁盤上,可以有效的改善MERGE表的訪問效率。 

MERGE存儲引擎是一組MyISAM表的組合,這些MyISAM表必須結構完全相同。MERGE表本身沒有數據,對MERGE類型的表進行查詢、更新、刪除的操作,就是對內部的MyISAM表進行的。 對此類表的插入操作,是通過insert_method子句定義的表,可以有3個不同值:first:作用在第一個表上;last:作用在最後一個表上;不定義或定義爲'no':不能對這個merge表進入插入操作。當對其進行drop時,只是刪除了merge的定義,而對內部表內容沒有影響。
merge表在磁盤上有兩個相關文件,一個是'.frm'文件存儲表定義,另一個'.mrg'文件包含了組合表的信息,由哪些表組成、插入數據時的依據規則。可以直接通過編輯'.mrg'文件來修改其內容,後通過'flush tables'來刷新生效。

示例
mysql> create table art10 like freeoa.content;
mysql> create table art11 like freeoa.content;
mysql> create table art12 like freeoa.content;

insert into art10(id,title,created,hits) select id,title,created,hits from freeoa.content where year(created)=2010 limit 5;

art11與art12表採取類似的操作,插入相關年份的一些記錄。

創建主表,這裏採用複製其它表的方法,快速而不容易出錯。
mysql> create table art like art10;
mysql> alter table art engine=merge union(art10,art11,art12) insert_method=last;

mysql> show create table art;
......
ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 INSERT_METHOD=LAST UNION=(`art10`,`art11`,`art12`)

且從art表全部查詢出的記錄數目爲各個子表的記錄數之和。

當向art表中插入記錄時,會插入到最後一張子表中:即art12表,即使這條記錄是2011年的。這也正是merge表與分區表之間的區別,merge表並不能智能地將記錄寫到對應的表中,而分區是支持此類邏緝的,它們在使用上是透明的。需要注意的是,分區表不是存儲引擎。

如何選擇合適的存儲引擎
選擇標準: 根據應用特點選擇合適的存儲引擎,對於複雜的應用系統可以根據實際情況選擇多種存儲引擎進行組合。下面是常用存儲引擎的適用環境:
1、MyISAM:默認的MySQL插件式存儲引擎,它是在Web、數據倉儲和其他應用環境下最常使用的存儲引擎之一
2、InnoDB:用於事務處理應用程序,具有衆多特性,包括ACID事務支持
3、Memory:將所有數據保存在RAM中,在需要快速查找引用和其他類似數據的環境下,可提供極快的訪問
4、Merge:允許MySQL DBA或開發人員將一系列等同的MyISAM表以邏輯方式組合在一起,並作爲1個對象引用它們。對於諸如數據倉儲等VLDB環境十分適合。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章