1.二叉樹/平衡樹.B-tree.B+tree.B*tree
樹:最上一層是根節點.最底下一層是葉子節點.(一般左邊節點小於右邊節點) 二叉樹:每個節點最多只能有兩個分支,一般只用於教材.二叉樹的深度不可控,造成遍歷數據時IO次數不可控.數據量大了,樹的深度會太大. 二叉樹的變種:BTREE(又寫成B-tree),B+tree和B*tree. B-tree即balance-tree:平衡樹:假設1個節點的子節點是5個,平衡樹是必須上層節點都滿了,才可加到下層.這樣樹的深度就得到了控制.B-tree除了在葉子節點保存數據,在非葉子節點也保存數據. B+tree:所有數據都存儲在葉子節點,非葉子節點不存儲數據.且葉子節點間構成了雙向鏈表。Mysql用的方法是B+tree. b+tree的插入必須要保證插入后,葉子節點的數據依然有序。而且不管怎么變化,根節點到葉子節點的深度始終是相同的。 B*tree:也只在葉子節點存儲數據並構成雙向指針,但在非葉子節點有雙向指針。 |
2.聚簇索引表(索引組織表cluster-index)
在建表時,innodb將表結構數據,存儲在一個B+TREE中,B+TREE叫聚簇索引(cluster-index).以聚簇索引構建的表叫聚簇索引表,又稱索引組織表。聚集索引頁的葉子節點匯總存放着完整的記錄,副主索引頁中存放着指向葉子的指針。 聚集索引是通過將表的主鍵作為鍵值來構造B+樹的,因為innoDB存儲引擎是通過主鍵來構造的,所以這需要每一張表都有主鍵,如果沒有顯式的指定主鍵,那么數據庫是自動創建主鍵,聚集索引不僅僅包含索引的鍵值,還包含了記錄所在其他列的值,聚集索引中的記錄是根據鍵值順序排列的,但是不是物理排序,而是順序排序。 說明: 1.根據主鍵尋址速度很快 2.主鍵值遞增的insert插入效率較好 3.主鍵值隨機insert插入操作效率差 建議:innodb表必須指定主鍵,最好使用自增數字; |
1.聚簇索引構建規則
1.存在主鍵的情況下,是用主鍵來構建聚簇索引. 2.在沒有主鍵的情況下,如果有唯一性非空索引,就用該索引構建. 3.都沒有,則開辟一個6字節的隱藏列,用隱藏列構建主鍵索引. |
2.聚簇索引的特點:
1. MySQL的表結構由聚簇索引來構建,表結構本身就是索引的一部分。 2.通過表的主鍵來鍵值來構造B+TREE,因為INNODB存儲引擎是一個索引組織表,這意味着每張表都有一個主鍵,如果沒有顯示的創建,則innodb會創建一個六個字節的主鍵,聚簇索引不僅僅包含索引的鍵值,還包含了記錄其他列的信息。 3.聚簇索引是根據鍵值順序存放的,然而要特別注意的是這個順序是指邏輯順序,而不是物理上的存儲順序。因為如果是物理順序那么排序開銷是不被接受的。 4.聚簇索引的非葉子結點存儲的是<</font>鍵值,地址>對。地址為指向下一層的指針,innoDB存儲引擎通過頁在表空間中的偏移量來表示。 5.創建表如果指定主鍵,那么會自動以指定的主鍵進行查詢,互聯網業務中,大多數的OLTP業務中,都是根據主鍵來查詢數據,同時查詢速度也是非常快的。 |
3.行數據庫表的兩大類(索引組織表和堆表)
索引組織表(聚簇索引表)—>MySQL默認表結構:表本身就是一個索引,數據按照主鍵的順序來進行組織。 堆表(普通的堆表,數據塊構成)—>ORACLE默認表結構(ORACLE也支持索引組織表,但是默認ORACLE的主鍵會默認創建索引)插入數據是隨機的 |
4.聚簇索引葉子節點塊
1.數據頁讀取到內存,所以對頁的操作,首先是在內存中操作的,那么就造成一個問題,某一時間,內存和硬盤的數據頁數據不一樣,這是通過事務ACID來可以保證,某一個時間點兩者的數據會到達最終一致性. 2.數據頁在磁盤或者內存空間中,是一次性開辟的,里面的記錄是順序線性存放的(邏輯上的) 3.葉記錄是根據主鍵順序排列的,這個順序是邏輯上的。 |
5.數據頁定位數據記錄的過程
在非葉子節點查找數據到葉子節點后,並無法定位數據,在數據頁中有一部分叫做page directory,該部分記錄了每個數據目錄在數據頁中的偏移量,知道偏移量后,進行二分法查找,就可以找到了具體的數據記錄. |
6.索引優點與缺點
索引優點: 1.加快數據檢索效率; 2.可以創建唯一性約束索引,保證數據庫表中每一行數據的唯一性; 3.加速表和表連接效率; 4.在使用分組和排序子句進行數據檢索時,可以顯著減少查詢中分組和排序的時間。 說明: 1.索引可以優化DML操作的查詢部分。 2. 索引提供了查詢的可控性,全表查詢IO不可控。 3. 索引查詢一條數據的IO次數由索引的層數決定。 索引缺點: 1.索引需要占用更多物理存儲空間。 2.當對表中的數據進行增加、刪除和修改的時候,索引也要更新維護,降低了數據維護效率。 說明:1.盡量在表里不要有冗余索引。2.大數據入庫時,可以先干掉索引,插入數據,然后重建索引。 |
7.索引分類
邏輯上: Single column indexes單列索引 Combined Indexes,Multiple-Column Indexes 多列索引 Unique 唯一索引 NonUnique 非唯一索引 物理上: clustered index 聚簇索引 not-clustered index非聚簇索引 復合索引:(建立在多個列上的索引) |
8.哪些情況下建議創建索引:
· 經常需要搜索的列 · 作為主鍵的列,有唯一約束索引 · 經常用在表連接的列 · 經常需要排序的列 · 經常使用在WHERE子句中的列 |
3.輔助索引
輔助索引又稱二級索引或非聚簇索引.
1.輔助索引存放的信息
輔助索引也是B+tree,葉子節點存放的是索引列和主鍵值,不存放其他列信息.若無主鍵,則存放的是索引列和該表聚簇索引的虛擬主鍵值.輔助索引是根據索引列的值排序. |
2.聚簇索引和輔助索引的選擇
1. 在聚簇索引和輔助索引都存在的時候,優化器傾向於使用聚簇索引,因為聚簇索引可以通過葉子節點找到數據。 2. 通過輔助索引查詢記錄僅僅只能得到主鍵值,要查詢完整的記錄,還需要通過一次聚簇索引查詢。(回表) 3. 僅僅當主鍵值發生改變的時候,需要更新輔助索引。(問題:索引列改變了難道不更新?) 4. 聚簇索引通常比輔助索引的高度要高(輔助索引不保存所有記錄,更小,高度更低)。 |
4.索引覆蓋、回表與復合索引
1.覆蓋索引
覆蓋索引:只需通過輔助索引就可以返回數據。 一個查詢語句的執行只需要從輔助索引中就可以得到查詢記錄,而不需要查詢聚集索引中的記錄。也可以稱之為實現了索引覆蓋。特高頻SQL,強烈推薦使用覆蓋索引,可以非常大的提高查詢效率。 |
2.回表
指當通過輔助索引查詢得到的記錄信息不足,需要回表再通過聚簇索引查詢信息. |
3.復合索引
復合索引:建立在多個列上的索引.. 關於復合索引的使用:遵從最左前綴原則。如當復合索引列有3個時,where條件里是1或者1、2或者1、 2、 3或者1、3時才可用到復合索引.其他查詢都不會用到復合索引。 |
4.mysql的ICP(索引下推)和對where中過濾條件的處理
ICP:Index Condition Pushdown(索引下推) ICP技術是在MySQL5.6中引入的一種索引優化技術。它能減少在使用二級索引過濾where條件時的回表次數和減少MySQL server層和引擎層的交互次數。在索引組織表中,使用二級索引進行回表的代價相比堆表中是要高一些的。 a 當關閉ICP時,index 僅僅是data access 的一種訪問方式,存儲引擎通過索引回表獲取的數據會傳遞到MySQL Server層進行where條件過濾。 b 當打開ICP時,如果部分where條件能使用索引中的字段,MySQL Server 會把這部分下推到引擎層,可以利用index過濾的where條件在存儲引擎層進行數據過濾,而非將所有通過index access的結果傳遞到MySQL server層進行where過濾. 優化效果:ICP能減少引擎層訪問基表的次數和MySQL Server 訪問存儲引擎的次數,減少io次數,提高查詢語句性能. 對where中過濾條件的處理,根據索引使用情況分成了三種:index key, index filter, table filter 1. index key----確定查詢范圍 用於確定SQL查詢在索引中的連續范圍(起始范圍+結束范圍)的查詢條件,被稱之為Index Key。由於一個范圍,至少包含一個起始與一個終止,因此Index Key也被拆分為Index First Key和Index Last Key,分別用於定位索引查找的起始,以及索引查詢的終止條件。也就是說根據索引來確定掃描的范圍。 2. index filter---索引過濾 在使用 index key 確定了起始范圍和介紹范圍之后,在此范圍之內,還有一些記錄不符合where 條件,如果這些條件可以使用索引進行過濾,那么就是index filter。也就是說用索引來進行where條件過濾。 3. table filter---條件過濾 where中的條件不能使用索引進行處理的,只能訪問table,進行條件過濾了。也就是說各種各樣的 where 條件,在進行處理時,分成了上面三種情況,一種條件會使用索引確定掃描的范圍;一種條件可以在索引中進行過濾;一種必須回表進行過濾;所以所謂的 ICP 技術,其實就是 index filter 技術而已。只不過因為MySQL的架構原因,分成了server層和引擎層,才有所謂的“下推”的說法。所以ICP其實就是實現了index filter技術,將原來的在server層進行的table filter中可以進行index filter的部分,在引擎層面使用index filter進行處理,不再需要回表進行table filter。 |
5.索引添加刪除語句
添加聚簇索引: alter table t1 add primary key (id); ---設置id為主鍵 添加輔助索引: alter table t1 add index idx_name (name); ---索引名為idx_name 刪除索引: drop index in_a on t1; |
6.索引掃描說明
在語句前加上explain.查看使用哪個索引.key字段的值為使用的索引名,rows字段的值為查詢過程中掃描到的數據的行數.最后的Extra若是Using index,則說明是走覆蓋索引.當查詢一條或幾條數據,使用了聚簇索引.key為primary. 當查詢字段是輔助索引列時,走輔助索引.這種不是通過覆蓋索引,故是先通過輔助索引再回表,通過聚簇索引查找數據. key顯示為輔助索引名稱.Extra顯示為null. 覆蓋索引:Using-index只需通過輔助索引就達到結果.沒有通過聚簇索引,故是覆蓋索引,key為輔助索引名稱,Extra顯示為Using index. |
7.唯一索引說明:
唯一(具有唯一約束的索引,唯一索引):唯一:不能有相同數據 alter table t add unique idx_t1(name). 添加唯一索引時,若該列值有重復,則不能添加.添加成功后,則該列有了唯一約束. |
8.索引的可選擇性
索引選擇性越高,索引的價值越高 索引可選擇性的計算: show index from t1; 后會有一行Cardinality,是不重復記錄的預估值(對列去重)。 使用Cardinality/rows就可以得到可選擇率,越接近1,索引越高效,其值介於(0,1] 舉例: 1. 字段‘gender’,可能有‘男’,‘女’,‘其他’三個值,索引的選擇性為 3/1000 = 0.003 2. 字段id,每條記錄都不同,索引選擇性為1000/1000 = 1 那么查詢id為123456且gender為‘女’的記錄時應該使用哪個索引? 顯然應該使用id字段上的索引,只要定位到這條索引記錄,就可以立刻確定是否存在這條記錄,然后再驗證性別是否為‘女’,而使用‘gender’字段上的索引,可能需要遍歷多條記錄,對比id后才能確定是否存在這條記錄. 再舉一個極端的情況:如果上述表中所有記錄的‘gender’字段都為‘女’,那么索引的選擇性為1/1000 = 0.001,這時使用‘gender’字段上的索引和全表掃描沒啥兩樣
|