數據庫存儲引擎的選擇會對性能產生直接的影響。MySQL體系結構如下:
存儲引擎是針對於表的而不是針對於庫的(一個庫中的不同表可以使用不同的存儲引擎)。MyISAM 是 MySQL 5.5 之前版本默認的存儲引擎。MySQL 5.5 及之後版本默認存儲引擎改爲了 InnoDB。
MyISAM 和 InnoDB 是最常用的兩種存儲引擎,除了這兩種,還有一些具備特殊功能的存儲引擎:CSV、Archive、Memory、Federated。簡單對比如下:
存儲引擎 | 事務 | 鎖粒度 | 索引和數據存儲 | 主要應用 | 忌用 |
---|---|---|---|---|---|
MyISAM | 不支持 | 支持併發插入的表級鎖 | 會把索引緩存在內存中,而數據通過操作系統來進行緩存 | select, insert | 讀寫操作頻繁 |
MRG_MyISAM | 不支持 | 支持併發插入的表級鎖 | 分段歸檔,數據倉庫 | 全局查找過多的場景 | |
InnoDB | 支持,事務 ACID 特性 | 支持MVCC的行級鎖 | 會同時在內存中緩存索引和數據,從而提高數據庫的運行效率 | 事務處理 | 無 |
Archive | 不支持 | 行級鎖 | 日誌記錄,只支持insert, select | 需要隨機讀取,更新,刪除 |
1.MyISAM
MySQL 大部分系統表和臨時表(在排序、分組等操作中,當數量超過一定大小後,由查詢優化器建立的臨時表)還是使用的 MyISAM。MyISAM 存儲引擎表由 MYD 和 MYI 組成。
特性:
1、併發性與鎖級別:非事務性存儲引擎,不支持事務,表級鎖。
在讀取數據時,MyISAM 會對整個表加共享鎖,但是共享鎖之間是不會阻塞的。共享鎖就是多個事務對於同一數據可以共享一把鎖,都能訪問到數據,但是隻能讀不能修改。
MyISAM 表在執行查詢操作的時候,其他進程對該表的讀操作沒有影響,但是寫操作會發生阻塞,直到第一個獲得讀鎖的進程操作完成釋放完讀鎖後,寫操作才能進行。
2、表損壞修復:
check table tablename //對錶進行檢查
repair table tablename //對錶進行恢復
3、MyISAM 表支持全文索引和空間函數。
4、MyISAM 表支持數據壓縮,myisampack 命令。
限制:
1、版本 < MySQL 5.0 時默認單表最大文件爲 4GB,如需存儲大表則要修改 MAX_Rows 和 AVG_ROW_LENGTH;版本 >= MySQL 5.0 時默認單表最大文件爲 256TB。
適用場景:
1、非事務型應用;
2、只讀類應用(支持數據壓縮,共享鎖之間是不會阻塞);
3、空間類應用(GPS 數據等)。
2.InnoDB
InnoDB 有自己表空間的概念,InnoDB 使用表空間進行數據存儲。具體存在什麼樣的表空間,則由 innodb_file_per_table 這個參數來決定,如果這個參數爲 ON,則會爲每個 InnoDB 表建立一獨立的表空間(tablename.ibd),爲 OFF 時則會把數據存儲到系統的共享表空間(ibdataX,X代表的是一個從1開始的數字)。
在 MySQL 5.6 之前版本 innodb_file_per_table 默認 OFF,MySQL 5.6 及之後版本默認 ON。
系統表空間和獨立表空間要如何選擇?
1、首先比較一下系統文件對錶空間的管理方式:
在一個繁忙的系統中,系統表空間會不斷增長,一旦磁盤空間出現不足,我們爲了釋放磁盤空間,不得不在系統中刪除大量的無效數據(長期不使用的、日誌類的數據),在刪除數據後,系統表空間並不會縮小,在這種情況下,我們想通過複製文件的方式對數據庫進行備份,由於雖然刪除了數據,但是文件大小並不會改變,這就意味着我們每次刪除時都要浪費很大的空間。
而想要收縮系統表空間的唯一方法就是把整個數據庫中的所有 InnoDB 表導出後,然後刪除 InnoDB 相關的表空間文件,再重啓 MySQL 進行表空間的重建,然後再導入數據,這個過程十分複雜,而且十分耗時。這在一個業務繁忙的生產環境中顯然是不可能做到的。
所以我們使用系統表空間進行數據存儲,所面臨的問題就是無法簡單的收縮文件大小,造成大量的空間浪費,並且會產生大量的磁盤碎片,降低系統性能。
而使用獨立表空間這個問題就很好解決了,當對一個大表中的數據進行清理之後,可以很方便的使用 optimize table 命令對這一個表進行收縮系統文件操作,雖然這種方式也會對一個表進行重建,但是對比整個系統進行重建要快的多,而且不需要重啓數據庫服務器,甚至不會影響正常訪問。
2、比較一下這兩種表空間對IO方面有哪些影響:
對於系統表空間,由於只有一個文件,如果同時對多個表進行數據刷新時,實際上在文件系統層面上是順序進行的,會產生I/O瓶頸。
獨立表空間每一個表都有自己的表空間文件,可以同時向多個文件刷新數據。
到此,可以發現,使用獨立表空間要比使用系統表空間好的多,建議對 InnoDB 使用獨立表空間進行數據存儲。
特性:
1、併發性與鎖級別:事務性存儲引擎,完美支持行級鎖(行級鎖比表級鎖支持更大的併發,吞吐量也會越高),事務 ACID 特性。
爲了實現事務的原子性、一致性、持久性,InnoDB 引用了兩個特殊的日誌類型 Redo Log(重做日誌)和 Undo Log(回滾日誌)。
行級鎖可以最大程度的支持併發;
行級鎖是在存儲引擎層實現的。
2、InnoDB 狀態檢查
show engine innodb status
3、MySQL 5.7 及之後版本,InnoDB 表開始支持全文索引和空間函數。
適用場景:
1、InnoDB 適用於大多數 OLTP 應用。
附一:把原來存儲在系統表空間中的錶轉移到獨立表空間中的方法:
- 使用 mysqldump 導出所有數據庫表數據;
- 停止 MySQL 服務,修改參數,並刪除 InnoDB 相關文件;
- 重啓 MySQL 服務,重建 InnoDB 系統表空間;
- 重新導入數據。
附二:鎖
鎖是數據庫系統區別於文件系統的一個重要特性,鎖的主要作用是管理共享資源的併發訪問。
鎖用於實現事務的隔離性。對於未提交的事務,鎖定的數據是無法被其他事務所查詢到的,
鎖的類型 | 說明 | 索引和數據存儲 |
---|---|---|
共享鎖(也稱爲讀鎖) | 讀鎖是共享的,相互之間是不會被阻塞的,多個線程可以在同一時間讀取同一資源 | |
獨佔鎖(也稱爲寫鎖) | 寫鎖是排他的,一個寫鎖會阻塞其他的讀鎖和寫鎖,這是出於數據完整性的考慮,保證了在給定的時間裏,只有一個線程能執行寫入並防止其他用戶讀取正在寫入的資源 |
看下兼容性:
- | 寫鎖 | 讀鎖 |
---|---|---|
寫鎖 | 不兼容 | 不兼容 |
讀鎖 | 不兼容 | 兼容 |
3.CSV
CSV 存儲引擎可以將 CSV 文件作爲 MySQL 的表來處理,存儲格式就是普通的 CSV 文件,CSV 文件如果存儲在 MyISAM 或 InnoDB 中, 數據文件是不能直接查看的,因爲 MyISAM 和 InnoDB 存儲格式都是以二進制格式進行存儲的。
當我們在 MySQL 中建立了一個 CSV 存儲引擎的表時,我們可以看到三個文件系統中的文件,這三個文件是以表名爲文件名的,表數據存儲在 CSV 爲後綴的文件中,表的元數據(如表狀態、數據量 )存儲在 .CSM 爲後綴的文件中,表結構信息存儲在 .frm 爲後綴的文件中。
特點:
1、以 CSV 格式進行數據存儲,CSV 格式中的每一列都是以逗號分割的,文本數據是以雙引號引起來的;
2、在建表時所有列的定義必須非 NULL 的;
3、不支持索引,索引的主要作用就是優化查詢效率,CSV 不支持索引,那麼每次查詢都會進行全表掃描,不適合大表,不適合在線處理;
4、可以對數據文件直接編輯(其他存儲引擎都是以二進制格式來存儲的,不可編輯);
適用場景:
1、適合做爲數據交換的中間表(可以將 Excel 文件存儲爲 CSV 文件,然後複製到 MySQL 數據目錄下,就能在 MySQL 中打開使用了);
4.Archive
Archive 存儲引擎會緩存所有的寫,並且利用 zlib 算法對錶數據進行進行壓縮,磁盤 I/O 更少。比 MyISAM 和 InnoDB 更加節約磁盤空間。
Archive 表數據存儲在 ARZ 爲後綴的文件中,表結構信息存儲在 .frm 爲後綴的文件中。
特點:
1、Archive 只支持 insert 和 select 操作,支持行級鎖和專用的緩衝區,所以可以實現高併發的插入;
2、只允許在自增 ID 列上建立索引。
適用場景:
1、不需要修改和刪除數據的 日誌和數據採集類應用(無法在 OLTP 應用中使用)。
5.Memory
Memory 存儲引擎也稱爲 HEAP 存儲引擎,數據保存在內存中,Memory 表的數據是易丟失的,一旦 MySQL 被重啓,所有 Memory 表中的數據都會消失(表結構會保留)。
Memory 表數據存儲在內存中,表結構信息存儲在 .frm 爲後綴的文件中。
Memory 的 I/O 效率要比 MyISAM 高很多。
特點:
1、支持 HASH 索引(適合等值查找)和 BTree 索引(適合範圍查找);
2、所有字段都爲固定長度,就算我們在定義表時使用了 varchar(10),在存儲表時還是會使用 char(10);
3、不支持 BLOG 和 TEXT 等大字段;
4、Memory 使用的是表級鎖;
5、Memory 表的最大大小是由 max_heap_table_size 參數決定的,默認 16MB(對已經存在的 Memory 表修改大小是無效的,需要重建表)。
適用場景(Memory 數據易丟失,所以要求數據可再生):
1、用於查找或者是映射表,例如郵編和地區的對應表;
2、用於保存數據分析中產生的中間表;
3、用於緩存週期性聚合數據的結果表;
6.Federated
MySQL 中默認是禁止的,啓動 Federated 需要在 MySQL 啓動時增加 federated 參數。
特點:
1、Federated 存儲引擎提供了訪問遠程 MySQL 服務器上表的方法;
2、本地不存儲數據,數據全部放到遠程服務器上;
3、本地需要保存表結構和遠程服務器的連接信息。
適用場景:
1、偶爾的統計分析及手工查詢。
7.如何選擇正確的存儲引擎
無論是否需要事務支持,只要是不需要使用 InnoDB 不支持的特殊功能外,我們都應該在新的應用中使用 InnoDB 存儲引擎。
如果不想使用 InnoDB,非要從衆多存儲引擎中進行篩選,可以參考以下幾個因素:
1、應用是否需要事務支持?
InnoDB 是目前最穩定的支持事務的存儲引擎,所以還是選擇 InnoDB 吧 。
2、備份?
只有 InnoDB 有在線熱備方案,其他存儲引擎要麼不能在線熱備,要麼是收費的方案,所以還是選擇 InnoDB 吧 。
mysqldump 並不是熱備方案,這裏注意一下。
3、崩潰恢復?
一般而言,MyISAM 發生崩潰後損壞數據的概率要比 InnoDB 高很多。MyISAM 恢復速度也慢,因此即使不需要事務支持,很多時候也要選擇 InnoDB 存儲引擎。
4、存儲引擎的特有特性?
比如很多應用依賴聚集索引進行優化,那麼就要選擇 InnoDB。
有些應用需要使用地理空間搜索,如果使用的是 MySQL 5.7 之前的版本,只能使用 MyISAM 了,如果使用得是 MySQL 5.7 及之後的版本,還是應該使用 InnoDB。
一個數據庫中,除非萬不得已,否則不建議混合使用多種存儲引擎,不然可能會帶來一些複雜的問題和潛在的 bug。比如混合使用 MyISAM 和 InnoDB,一旦在一個事務中對兩種存儲引擎的表進行操作,如果出現回滾,只有 InnoDB 表中的數據會回滾,而 MyISAM 不回滾,這樣就會給應用帶來數據邏輯上的一些問題。