1. 程式人生 > >MySQL:存儲引擎介紹

MySQL:存儲引擎介紹

相等 ndb存儲 處理 調整 現實生活 inf 性能 例如 依賴

前言,什麽是存儲引擎

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:存儲引擎介紹