B+樹索引分爲彙集索引和非彙集索引(輔助索引),可是二者的數據結構都和B+樹同樣,區別是存放的內容。html
能夠說數據庫必須有索引,沒有索引則檢索過程變成了順序查找,O(n)的時間複雜度幾乎是不能忍受的。咱們很是容易想象出一個只有單關鍵字組成的表如何使用B+樹進行索引,只要將關鍵字存儲到樹的節點便可。當數據庫一條記錄裏包含多個字段時,一棵B+樹就只能存儲主鍵,若是檢索的是非主鍵字段,則主鍵索引失去做用,又變成順序查找了。這時應該在第二個要檢索的列上創建第二套索引。 這個索引由獨立的B+樹來組織。有兩種常見的方法能夠解決多個B+樹訪問同一套表數據的問題,一種叫作聚簇索引(clustered index ),一種叫作非聚簇索引(secondary index)。這兩個名字雖然都叫作索引,但這並非一種單獨的索引類型,而是一種數據存儲方式。對於聚簇索引存儲來講,行數據和主鍵B+樹存儲在一塊兒,輔助鍵B+樹只存儲輔助鍵和主鍵,主鍵和非主鍵B+樹幾乎是兩種類型的樹。對於非聚簇索引存儲來講,主鍵B+樹在葉子節點存儲是指向真正數據行的指針,而且輔助B+樹在葉子節點存儲也是指向真正數據行的指針,而非主鍵B+樹。算法
InnoDB使用的是聚簇索引,將主鍵組織到一棵B+樹中,而行數據就儲存在葉子節點上,若使用"where id = 14"這樣的條件查找主鍵,則按照B+樹的檢索算法便可查找到對應的葉節點,以後得到行數據。若對Name列進行條件搜索,則須要兩個步驟:第一步在輔助索引B+樹中檢索Name,到達其葉子節點獲取對應的主鍵。第二步使用主鍵在主索引B+樹種再執行一次B+樹檢索操做,最終到達葉子節點便可獲取整行數據。sql
InnoDB存儲引擎是索引組織表,也就是說數據文件自己就是按照B+樹方式存放數據的。Innodb 彙集索引是按照主鍵(primary key)進行彙集,被索引的列實際上是主鍵列,若是沒定義主鍵,Innodb會試着使用惟一非空索引Unique Index來代替,若是還找不到,Innodb就會自動建立一個6字節做爲隱藏主鍵而後在上面進行索引彙集。除了主鍵的彙集索引,其餘索引(輔助索引)中不會保存行的物理位置,而是保存主鍵的值,因此經過"二級索引"進行查找是先找到主鍵,再找到行,要進行二次索引查找。在InnoDB存儲引擎中,將B+樹索引分爲彙集索引和非彙集索引(輔助索引),可是二者的數據結構都和B+樹同樣,區別是存放的內容。不管是何種索引,每一個頁的大小都是16KB,且不能改變。數據庫
MyISM使用的是非聚簇索引,非聚簇索引的兩棵B+樹看上去沒什麼不一樣,節點的結構徹底一致只是存儲的內容不一樣而已,主鍵索引B+樹的節點存儲了主鍵,輔助鍵索引B+樹存儲了輔助鍵。表數據存儲在獨立的地方,這兩顆B+樹的葉子節點都使用一個地址指向真正的表數據,對於表數據來講,這兩個鍵沒有任何差異。因爲索引樹是獨立的,經過輔助鍵檢索無需訪問主鍵的索引樹。數據結構
圖示清晰的顯示了聚簇索引和非聚簇索引的差別。性能
並非全部在查詢條件中出現的列都須要添加索引,對於何時添加B+樹索引,通常的檢驗是,在訪問表中不多一部分行是使用B+樹索引纔有意義。查看索引是不是高選擇性的,能夠經過SHOW INDEX語句中的Cardinality列來觀察。Cardinality是一個估計值,在實際中,Cardinality/n_rows_in_table應儘量接近1,若是很是小,那麼須要考慮是否還要建這個索引。優化
InnoDB中如何統計Cardinality值,索引的更新可能很是平凡,若是每次更新操做時就統計Cardinality值,那麼對數據庫會帶來很大負擔。InnoDB存儲引擎中,Cardinality統計發生在INSERT和UPDATE操做中,不過並不會每次都去統計,它的策略是:指針
stat_modified_counter是數據庫發生INSERT和UPDATE操做的計數器,若是每次對錶中的一行數據更新操做,表中的數據幾乎不會有變化,那麼第一種策略就沒法試用。因此計數器用來統計操做的次數,若是知足條件,也會統計Cardinality值。htm
InnoDB存儲引擎只對8個葉節點進行採樣。採樣的過程爲:blog
注意:若是表足夠小,表的葉節點小於或等於8個,這時即便隨機採樣,也老是採起到這些頁,所以每次的Cardinality值都是同樣的。
數據庫存在兩種類型的應用:OLTP和OLAP應用。OLTP是傳統關係型數據庫的主要應用,其主要面向基本的、平常的事務處理,例如銀行交易。OLAP是數據倉庫系統的主要應用,支持複雜的分析操做,側重決策支持,而且提供直觀易懂的查詢結果。
在OLTP應用中,查詢操做通常只從數據庫中取得一小部分數據,在這種狀況下,創建B+樹索引後,優化器就會使用索引。對於OLAP應用,通常須要訪問表中的大量數據,並根據這些數據來產生查詢的結果,而這些查詢可能是分析的查詢,目的是爲決策者提供支持。可是對於LOAP中的複雜查詢,須要涉及多表之間的聯接操做,這是索引的添加是有意義的,可是聯接操做使用Hash Join,那麼索引可能又變得不是很是重要。不過在OLAP應用中,一般須要對時間字段進行索引,這是由於大多數統計須要根據時間維度來進行判斷。
聯合索引是指對錶上的多個列進行索引,又叫複合索引。對於複合索引:Mysql從左到右的使用索引中的字段,一個查詢能夠只使用索引中的一部份,但只能是最左側部分。例如索引是key index (a,b,c)。能夠支持a | a,b | a,b,c 3種組合進行查找,但不支持b,c進行查找。當最左側字段是常量引用時,索引就十分有效。查詢使用索引的條件不一樣通常組合索引須要按照「最左前綴」來執行查詢,並非每一個列都須要覆蓋,只是從左邊的列開始組合。在選擇組合索引的時候,當前Query 中過濾性最好的字段在索引字段順序中排列越靠前越好。
例若有索引key(a,b,c)
InnoDB存儲引擎支持覆蓋索引,即從輔助索引就能夠獲得查詢的記錄,而不須要查詢彙集索引中的記錄。使用覆蓋索引的好處是輔助索引不包含整行記錄的全部信息,故其大小要遠小於彙集索引,所以能夠減少大量的IO操做。
對於InnoDb存儲引擎的輔助索引而言,因爲其中包含了主鍵信息,所以其葉子節點放的數據爲(primary key1, primary key2,..., key1, key2,...)。對於下面的能夠僅用一次輔助聯合索引來完成查詢。
簡單的說,若是查詢的列,正好是咱們設置的主鍵或者鍵(創建聚合索引的鍵),如上圖展現的,輔助索引的葉子節點的值就是所要查詢的內容,就沒必要取到鍵值後再去聚合索引進行二次查找。能夠想到若是想要更多的使用覆蓋索引這一特性,須要將咱們須要的列,都創建聯合索引。
聯合索引和覆蓋索引有很大的區別:
覆蓋索引是查詢的列能夠直接經過索引提取,好比只查詢主鍵的列!或者查詢聯合索引的全部列或者左邊開始的部分列(注意有順序的)!
而聯合索引並不必定只從索引中能獲取到全部的數據,這個取決於你所查詢的列。好比select * from table where ××××××;的方式就不太多是覆蓋索引。所以若是你查詢的列能用到聯合索引,且你查詢的列都能經過聯合索引獲取,好比你只查詢聯合索引所在的列或者左邊開始的部分列,這就至關於覆蓋索引了。一般爲了讓查詢能用到覆蓋索引,就將要查詢的多列數據設置成聯合索引。
在某些狀況下,優化器並無選擇輔助索引去查找數據,而是經過掃描彙集索引,也就是直接進行全表的掃描來獲得數據。
SELECT * FROM orderdetails WHERE orderid>10000 and orderid<102000;
經過SHOW INDEX FROM orderdetails能夠看到可使用的索引包括PRIMARY、OrderID、OrderOrder_Details三個索引,正常狀況下,應該選擇OrderID輔助索引開始查詢,可是優化器直接選擇PRIMARY彙集索引。
緣由在於咱們要選取的數據是整行信息,而OrderID索引不能覆蓋到咱們要查詢的信息(覆蓋索引),所以在對OrderID索引進行查詢到指定數據的操做後,還須要進行一次書籤訪問來查找整行信息。雖然在輔助索引中數據是順序存放的,可是再一次的書籤查找數據是無序的,所以變爲了磁盤上的離散讀取操做。若是要訪問的數據量很小,那麼優化器仍是會選擇輔助索引,可是當訪問的數據佔整個表中數據的很大一部分時(通常是20%左右),優化器會選擇經過彙集索引來查找數據。
MYSQL數據庫支持INDEX HINT(索引提示),顯示的告訴優化器使用哪一個索引,在如下狀況下可能須要用到INDEX HINT:
SELECT * FROM t USE INDEX(a) WHERE a=1 AND b=2;
使用USE INDEX能夠告訴優化器能夠選擇該索引,可是不是強制使用該索引。實際的使用優化器仍是會根據本身的判斷進行選擇。
SELECT * FROM t FORCE INDEX(a) WHERE a=1 AND b=2;
使用FORCE INDEX能夠指定優化器選擇某個索引進行查詢。
對於MYSQL數據庫的NDB CLuster內存存儲引擎,在使用它時可將其視爲內存數據庫。在內存數據庫中,通常使用T樹做爲其索引的數據結構。T樹是有平衡二叉樹和B樹發展而來。T樹的好處是節點不存放數據,只存放指針,這樣能減小內存的使用,這對內存數據庫來講是很重要的。同時T樹也是一棵平衡二叉樹,以此保證查找的性能。
當前MYSQL數據庫中,Memory存儲引擎支持哈希索引。InnoDB存儲引擎支持自適應哈希索引,用戶僅能開啓該特性,不能對其進行人工干預。經過參數innodb_adaptive_hash_index來禁用或啓動此特性,默認爲開啓。
轉載請註明出處。
做者:wuxiwei
出處:http://www.cnblogs.com/wxw16/p/6131132.html