前言
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。