(一)關於存儲引擎 mysql
建立合適的索引是SQL性能調優中最重要的技術之一。在學習建立索引以前,要先了解MySql的架構細節,包括在硬盤上面如何組織的,索引和內存用法和操做方式,以及存儲引擎的差別如何影響到索引的選擇。面試
MySQL有不少種衍生版本,這些衍生版本支持更多不一樣種類的存儲引擎。本文主要討論三種MySQL引擎。算法
MyISAM一種非事務性的存儲引擎,是MySQL 5.5以前版本默認的存儲引擎。sql
InnoDB 最流行的事務性存儲引擎,從5.5版開始成爲MySQL默認的引擎。數據庫
Memory 基於內存的,非事務性的以及非持久性的存儲引擎。緩存
注意:數據結構
從5.5版本開始,MySQL表的默認存儲引擎從MyISAM換成InnoDB,將會使用戶安裝那些依賴默認設置或者專門爲MyISAM編寫的軟件包時帶來很大的影響。架構
(二)MySQL索引類型性能
MySQL支持在全部關係數據庫表中建立主鍵、惟一鍵、不惟一的非主碼索引等多種類型的索引。此外MySQL還支持純文本和空間索引類型。學習
MySQL內置的存儲引擎對各類索引技術有不一樣的實現方式,包括:B-樹,B+樹,R-樹以及散列類型。
索引數據結構理論:
1.B-樹
B-樹中有兩種節點類型:索引節點和葉子節點。葉子節點是用來存儲數據的,而索引節點則用來告訴用戶存儲在葉子節點中的數據順序,並幫助用戶找到相應的數據。
B-樹的搜索,從根節點開始,對節點內的關鍵字有序進行二分查找,若是命中則結束,不然進入查詢關鍵字所屬範圍的兒子節點,重複。直到所對應的兒子指針爲空,或已是葉子節點。
B-樹是一種多路搜索樹:
(1). 定義任意非葉子節點最多有M個兒子,且M>2;
(2). 根節點的兒子數爲[2,M];
(3). 除根節點之外的非葉子節點的兒子數爲[M/2,M];
(4). 每一個節點存放至少M/2-1(取上整)和至多M-1個關鍵字;
(5). 非葉子節點的關鍵字個數=指向兒子節點的指針的個數-1;
(6). 非葉子節點的關鍵字:k[i]
(7). 非葉子節點的指針:p[1],p[2],·····,p[M];其中p[1]指向的關鍵字小於k[1]的子樹,p[M]指向的關鍵字大於K[m-1]的子樹;
(8). 全部的葉子節點位於同一層;
2.B+樹
B+樹數據結構是B-樹實現的加強版本。儘管B+樹支持B-樹索引的全部特性,它們之間最顯著的不一樣點在於B+樹中底層數據是根據被說起的索引列進行排序的。B+樹還經過葉子節點之間的附加引用來優化掃描性能。
B+搜索和B-搜索不一樣,區別是B+樹只有達到葉子節點才命中(B-樹能夠在非葉子節點命中),其性能等價於關鍵字全集作一次二分搜索。
B+樹的特性:
(1)全部關鍵字都出如今葉子節點的鏈表中,葉子節點至關於存儲數據的數據層。
(2)不可能在非葉子節點上命中。
(3)非葉子節點至關因而葉子節點的索引,葉子節點至關於數據層。
3.散列
散列表數據結構是一種很簡單的概念,它將一種算法應用到給定值中以在底層數據存儲系統中返回一個惟一的指針或位置。散列表的優勢是始終以線性時間複雜度找到須要讀取的行的位置,而不像B-樹那樣須要橫跨多層節點來肯定位置。
4.通訊R-樹
R-樹數據結構支持基於數據類型對幾何數據進行管理。目前只有MyISAM使用R-樹實現支持空間索引,使用空間索引也有不少限制,好比只支持惟一的NOT NULL列等。
5.全文本
全文本結構也是一種MySQL採用的基本數據結構。這種數據結構目前只有當前版本MySQL中的MyISAM存儲引擎支持。5.6版本將要在InnoDB存儲引擎中加入全文本功能。全文本索引在大型系統中並無什麼實用的價值,由於大規模系統有不少專門的文件檢索產品。因此不用在介紹。
MySQL實現
對B-樹,B+樹和散列等數據結構的基本概念有了一些瞭解以後,咱們就能夠開始討論MySQL經過支持它們的存儲引擎如何實現不一樣的算法。同時每種實現也對磁盤和內存使用狀況有不一樣的影響,這一點在大型數據庫系統中是很是重要的考慮因素。
1.MyISAM的B-樹
MyISAM存儲引擎使用B-樹數據結構來實現主碼索引、惟一索引以及非主碼索引。在MyISAM實現數據目錄和數據庫模式子目錄中,用戶能夠找到和每一個MySQL表對應的.MYD和.MYI文件。數據庫表上定義的索引信息就存儲在MYI文件中,該文件的塊大小是1024字節。這個大小是能夠經過myisam-block-size系統變量分配。
$ ls -1h /var/lib/mysql/book/source_words.MY*
-rw-rw---- 1 mysql mysql 9.2M 2015-05-07 19:08
source_words.MYD
-rw-rw---- 1 mysql mysql 7.8M 2015-05-07 19:08
source_words.MYI
這些文件結構的內部格式能夠從MySQL免費源代碼中找到,也能夠查看MySQL內部手冊。
在MyISAM中,非主碼索引的B-樹結構存儲索引值和一個指向主碼數據的指針,這是MyISAM和InnoDB的一個顯著區別。這一點致使了兩個存儲引擎的索引的不一樣工做方式。
MyISAM索引是在內存的一個公共緩存中管理的,這個緩存的大小能夠經過key_buffer_size或者其餘命名鍵緩存來定義。這是根據統計和規劃的表索引的大小來設定緩存大小時主要的考慮因素。
2. InnoDB的B+樹聚簇主碼
InnoDB存儲引擎在它的主碼索引(也被稱爲聚簇主碼)中使用了B+樹,這種結構把全部數據都和對應的主碼組織在一塊兒,而且在葉子節點這一層上添加額外的向前和向後的指針,這樣就能夠更方便地進行範圍掃描。
在文件系統層面,全部InnoDB數據和索引信息都默認在公共InnoDB表空間中管理,不然管理員就經過innodb_data_file_path這個變量指定文件路徑。這是一個叫ibdatal文件。
因爲InnoDB用聚簇主碼存儲數據,底層信息佔用的磁盤空間的大小很大程度上取決於頁面的填充因子。對於按序排列的主碼,InnoDB會用16K頁面的15/16做爲填充因子。對於不是按序排列的主碼,默認狀況下InnoDB會插入初始數據的時候爲每個頁面分配50%做爲填充因子。
在改索引的實現方式中B+樹的葉子節點上是data就是數據自己,key爲主鍵,若是是通常索引的話,data便會指向對應的主索引。在B+樹的每個葉子節點上面增長一個指向相鄰葉子節點的指針,就造成了帶有順序訪問指針的B+樹。其目的是提升區間訪問的性能。
3.InnoDB的B-樹非主碼
InnoDB中的非主碼索引使用了B-樹數據結構,但InnoDB中的B-樹結構實現和MyISAM中並不同。在InnoDB中,非主碼索引存儲的是主碼的實際值。而MyISAM中,非主碼索引存儲的包含主碼值的數據指針。這一點很重要。首先,當定義很大的主碼的時候,InnoDB的非主碼索引可能回更大,隨着非主碼索引數量的增長,索引之間大小差異可能會變得很大。另外一個不一樣點在於非主碼索引當前能夠包含主鍵的值,而且能夠不是索引必須有的部分。
4.內存散列索引
在默認MySQL的引擎索引中,只有MEMORY引擎支持散列數據結構,散列結構的強度能夠表示爲直接鍵查找的簡單性,散列索引的類似度模式匹配查詢比直接查詢慢。也能夠爲MEMORY引擎指定一個B-樹索引實現。
5.內存B-樹索引
對於大型MEMORY表來講,使用散列索引進行索引範圍搜索的效率很低,B-樹索引在執行直接鍵查詢時確實比使用默認的散列索引快。根據B-樹的不一樣深度,B-樹索引在個別操做中的確可能比散列算法快。
6.InnoDB內部散列索引
InnoDB存儲引擎在聚簇B+樹索引中存儲主碼:但在InnoDB內部仍是使用內存中的散列表來更高效地進行主碼查詢。這個機制有InnoDB存儲引擎來管理,用戶只能經過innodb_adaptive_hash_index配置項來選擇是否啓用這個惟一的配置選項。
歡迎工做一到五年的Java工程師朋友們加入Java架構開發:744677563
本羣提供免費的學習指導 架構資料 以及免費的解答
不懂得問題均可以在本羣提出來 以後還會有職業生涯規劃以及面試指導