MySQL:存儲引擎介紹
前言,什麽是存儲引擎
mysql中建立的庫===>文件夾 庫中建立的表===>文件
現實生活中我們用來存儲數據的文件有不同的類型,每種文件類型對應各自不同的處理機制:比如處理文本用txt類型,處理表格用excel,處理圖片用png等
數據庫中的表也應該有不同的類型,表的類型不同,會對應mysql不同的存取機制,表類型又稱為存儲引擎。
存儲引擎說白了就是如何存儲數據、如何為存儲的數據建立索引和如何更新、查詢數據等技術的實現方
法。因為在關系數據庫中數據的存儲是以表的形式存儲的,所以存儲引擎也可以稱為表類型(即存儲和
操作此表的類型)
在Oracle 和SQL Server等數據庫中只有一種存儲引擎,所有數據存儲管理機制都是一樣的。而MySql
數據庫提供了多種存儲引擎。用戶可以根據不同的需求為數據表選擇不同的存儲引擎,用戶也可以根據
自己的需要編寫自己的存儲引擎
SQL 解析器、SQL 優化器、緩沖池、存儲引擎等組件在每個數據庫中都存在,但不是每 個數據庫都有這麽多存儲引擎。MySQL 的插件式存儲引擎可以讓存儲引擎層的開發人員設 計他們希望的存儲層,例如,有的應用需要滿足事務的要求,有的應用則不需要對事務有這 麽強的要求 ;有的希望數據能持久存儲,有的只希望放在內存中,臨時並快速地提供對數據 的查詢。
一,MySQL存儲引擎
存儲引擎說白了就是如何存儲數據、如何為存儲的數據建立索引和如何更新、查詢數據等技術的實現方法。因為在關系數據庫中數據的存儲是以表的形式存儲的,所以存儲引擎也可以稱為表類型(即存儲和操作此表的類型)。MySQL5.5以後默認使用InnoDB
下圖是MySQL中各種存儲引擎的對比。
1.MyISAM:
這種引擎是mysql最早提供的。它不支持事務,也不支持外鍵,尤其是訪問速度快。這種引擎又可以分為靜態MyISAM、動態MyISAM 和壓縮MyISAM三種:
1) 靜態MyISAM:如果數據表中的各數據列的長度都是預先固定好的,服務器將自動選擇這種表類型。因為數據表中每一條記錄所占用的空間都是一樣的,所以這種表存取和更新的效率非常高。 當數據受損時,恢復工作也比較容易做。這種存儲方式的優點是存儲非常迅速,容易緩存,出現故障容易恢復;缺點是占用的空間通常比動態表多。
2) 動態MyISAM:如果數據表中出現varchar、xxxtext或xxxBLOB字段時,服務器將自動選擇這種表類型。相對於靜態MyISAM,這種表存儲空間比較小,但由於每條記錄的長度不一,所以 多次修改數據後,數據表中的數據就可能離散的存儲在內存中,進而導致執行效率下降。同時,內存中也可能會出現很多碎片。因此,這種類型的表要經常用optimize table命令或者myisamchk -r命令 或 優化工具來整理碎片、改善性能,並且出現故障的時候恢復相對比較困難。
3) 壓縮MyISAM:以上說到的兩種類型的表都可以用myisamchk工具壓縮。這種類型的表進一步減小了占用的存儲,但是這種表壓縮之後不能再被修改。另外,因為是壓縮數據,所以這種表在讀取的時候要先時行解壓縮。但是,不管是何種MyISAM表,目前它都不支持事務,行級鎖和外鍵約束的功能。
2.Merge:
這種類型是MyISAM類型的一種變種。合並表是將幾個相同的MyISAM表合並為一個虛表。常應用於日誌和數據倉庫。
3.InnoDB:
InnoDB表類型可以看作是對MyISAM的進一步更新產品,它提供了事務、行級鎖機制和外鍵約束的功能。對比MyISAM的存儲引擎,InnoDB寫的處理效率差一些,並且會占用更多 的磁盤空間以保留數據和索引。
4.memory:
這種類型的數據表只存在於內存中。它使用HASH索引,所以數據的存取速度非常快。因為是存在於內存中,所以這種類型常應用於臨時表中,但是一旦服務器關閉,表中的數據就會丟失,但表還會繼續存在。默認情況下,memory數據表使用散列索引,利用這種索引進行“相等比較”非常快,但是對“範圍比較”的速度就慢多了。因此,散列索引值適合使用在"="和"<=>"的操作符中,不適合使用在"<"或">"操作符中,也同樣不適合用在order by字句裏。如果確實要使用"<"或">"或betwen操作符,可以使用btree索引來加快速度。
存儲在MEMORY數據表裏的數據行使用的是長度不變的格式,因此加快處理速度,這意味著不能使用BLOB和TEXT這樣的長度可變的數據類型。VARCHAR是一種長度可變的類型,但因為它在MySQL內部當作長度固定不變的CHAR類型,所以可以使用。
使用USING HASH/BTREE來指定特定到索引:create index mem_hash using hash on tab_memory(city_id);
5.archive:
這種類型只支持select 和 insert語句,而且不支持索引。常應用於日誌記錄和聚合分析方面。
6.BLACK HOLE:
黑洞存儲引擎,可以應用於主備復制中的分發主庫。
7.NDB存儲引擎:
2003年,MySQL AB 公司從 Sony Ericsson 公司收購了 NDB 存儲引擎。 NDB 存儲引擎是一個集群存儲引擎,類似於 Oracle 的 RAC 集群,不過與 Oracle RAC 的 share everything 結構不同的是,其結構是 share nothing 的集群架構,因此能提供更高級別的 高可用性。NDB 存儲引擎的特點是數據全部放在內存中(從 5.1 版本開始,可以將非索引數 據放在磁盤上),因此主鍵查找(primary key lookups)的速度極快,並且能夠在線添加 NDB 數據存儲節點(data node)以便線性地提高數據庫性能。由此可見,NDB 存儲引擎是高可用、 高性能、高可擴展性的數據庫集群系統,其面向的也是 OLTP 的數據庫應用類型。
8.NEST存儲引擎:
網易公司開發的面向其內部使用的存儲引擎。目前的版本不支持事務, 但提供壓縮、行級緩存等特性,不久的將來會實現面向內存的事務支持。
MySQL 數據庫還有很多其他存儲引擎,上述只是列舉了最為常用的一些引擎。如果 你喜歡,完全可以編寫專屬於自己的引擎,這就是開源賦予我們的能力,也是開源的魅 力所在。
二,存儲引擎如何選擇
是否支持事務 檢索和添加速度 鎖機制 緩存 是否支持全文索引 是否支持外鍵
三,MyISAM和InnoDB對比
四,什麽時候使用MyISAM和InnoDB
MyISAM:讀事務要求不高,以查詢和插入為主,可以使用這個引擎來創建表, 例如各種統計表。 InnoDB:對事務要求高,保存的是重要的數據 例如交易數據,支付數據等,對用戶重要的數據,建議使用InnoDB。
五,對存儲引擎的操作
1.查看數據庫默認的存儲引擎:
show engines; show variables like ‘default_storage_engine‘;
2.查看表的存儲引擎:
1) 顯示表的創建語句:
show create table tablename;
2) 顯示表的當前狀態值:
show table status like ‘tablename’ \G
3) 設置或修改表的存儲引擎
- 創建數據庫表時設置存儲存儲引擎的基本語法是:
create table tableName( columnName(列名1) type(數據類型) attri(屬性設置), columnName(列名2) type(數據類型) attri(屬性設置), ....) engine = engineName
- 修改存儲引擎,可以用命令
Alter table tableName engine = engineName
4)練習
創建四個表,分別使用innodb,myisam,memory,blackhole存儲引擎,進行插入數據測試
MariaDB [db1]> create table t1(id int)engine=innodb; MariaDB [db1]> create table t2(id int)engine=myisam; MariaDB [db1]> create table t3(id int)engine=memory; MariaDB [db1]> create table t4(id int)engine=blackhole; MariaDB [db1]> quit [root@egon db1]# ls /var/lib/mysql/db1/ #發現後兩種存儲引擎只有表結構,無數據 db.opt t1.frm t1.ibd t2.MYD t2.MYI t2.frm t3.frm t4.frm #memory,在重啟mysql或者重啟機器後,表內數據清空 #blackhole,往表內插入任何數據,都相當於丟入黑洞,表內永遠不存記錄
五,配置和數據文件
1.配置文件默認位置
Linux: /etc/my.cnf Windows: my.ini
2.數據文件位置
1) 查看數據文件位置的命令: show variables like ‘%datadir%‘ ;
2) 數據文件格式:
InnoDB:frm(存儲的表結構)、ibd(存儲的數據和索引)
MyISAM:frm(存儲的表結構)、MYD(存儲的數據)、MYI(存儲的索引)
六,數據庫表設計
1.第一範式
1) 概念:列不可分。每一列都是不可分割的基本數據項。
2) 例子:假設我們有一個學生表,字段包括:id,name,age,contact,如下:
當我們需要根據QQ來查詢學生的時候,就查詢不出,所以以上的設計就不符合1NF。我們可以將contact字段拆分為phone和QQ,如下:
這樣就滿足1NF了。
2.第二範式
1) 概念:1NF的基礎上面,非主屬性完全依賴於主關鍵字。
2) 例子:學生表:(學號, 姓名, 年齡, 課程名稱, 成績, 學分) ,從字段可以看出,此表聯合主鍵是(學號,課程名稱)。
存在如下決定關系:
1:(學號, 課程名稱) → (姓名, 年齡, 成績, 學分)
2:(課程名稱) → (學分)
3:(學號) → (姓名, 年齡)
其中,姓名、年齡、學分是部分依賴於主鍵的,而成績是完全依賴於主鍵的,存在部分依賴關系,所以不滿足第二範式。
這會造成如下問題:
(1) 數據冗余:
同一門課程由n個學生選修,"學分"就重復n-1次;同一個學生選修了m門課程,姓名和年齡就重復了m-1次。
(2) 更新異常:
若調整了某門課程的學分,數據表中所有行的"學分"值都要更新,否則會出現同一門課程學分不同的情況。
(3) 插入異常:
假設要開設一門新的課程,暫時還沒有人選修。這樣,由於還沒有"學號"關鍵字,課程名稱和學分也無法記錄入數據 庫。
(4) 刪除異常:
假設一批學生已經完成課程的選修,這些選修記錄就應該從數據庫表中刪除。但是,與此同時,課程名稱和學分信息也被刪除了。很顯然,這也會導致插入異常。
問題就在於存在非主屬性對主鍵的部分依賴。
解決辦法:把原表(學號, 姓名, 年齡, 課程名稱, 成績, 學分)分成三個表:
學生:Student(學號, 姓名, 年齡);
課程:Course(課程名稱, 學分);
選課關系:SelectCourse(學號, 課程名稱, 成績)。
3.第三範式
1) 概念:2NF的基礎上,屬性不依賴於其它非主屬性 , 消除傳遞依賴。第三範式又可描述為:表中不存在可以確定其他非關鍵字的非關鍵字段。
2) 例子:學生表:(學號, 姓名, 年齡, 所在學院, 學院地點, 學院電話),主鍵必然是學號。
由於主鍵是單一屬性,所以非主屬性完全依賴於主鍵,所以必然滿足第二範式。但是存在如下傳遞依賴:
(學號) → (所在學院) → (學院地點, 學院電話),
學院地點 和 學院電話傳遞依賴於學號,而學院地點和學院電話都是非關鍵字段,即表中出現了“某一非關鍵字段可以確定出其它非關鍵字段”的情況,於是違反了第三範式。
解決辦法:
把原表分成兩個表:
學生:(學號, 姓名, 年齡, 所在學院);
學院:(學院, 地點, 電話)。
MySQL:存儲引擎介紹