二、索引
1.什么是索引?
何為索引:
數據庫索引,是數據庫管理系統(tǒng)中一個排序的數據結構,索引的實現(xiàn)通常使用B樹及其變種B+樹。
在數據之外,數據庫系統(tǒng)還維護著滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現(xiàn)高級查找算法。這種數據結構,就是索引。
2.索引的作用?它的優(yōu)點缺點是什么?
索引作用:
協(xié)助快速查詢、更新數據庫表中數據。
為表設置索引要付出代價的:
- 一是增加了數據庫的存儲空間
- 二是在插入和修改數據時要花費較多的時間(因為索引也要隨之變動)。
#### **3.索引的優(yōu)缺點?**創(chuàng)建索引可以大大提高系統(tǒng)的性能(優(yōu)點):
1.通過創(chuàng)建唯一性索引,可以保證數據庫表中每一行數據的唯一性。
2.可以大大加快數據的檢索速度,這也是創(chuàng)建索引的最主要的原因。
3.可以加速表和表之間的連接,特別是在實現(xiàn)數據的參考完整性方面特別有意義。
4.在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。
5.通過使用索引,可以在查詢的過程中,使用優(yōu)化隱藏器,提高系統(tǒng)的性能。
增加索引也有許多不利的方面(缺點):
1.創(chuàng)建索引和維護索引要耗費時間,這種時間隨著數據量的增加而增加。
2.索引需要占物理空間,除了數據表占數據空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大。
3.當對表中的數據進行增加、刪除和修改的時候,索引也要動態(tài)的維護,這樣就降低了數據的維護速度。
4.哪些列適合建立索引、哪些不適合建索引?
索引是建立在數據庫表中的某些列的上面。在創(chuàng)建索引的時候,應該考慮在哪些列上可以創(chuàng)建索引,在哪些列上不能創(chuàng)建索引。
一般來說,應該在這些列上創(chuàng)建索引:
(1)在經常需要搜索的列上,可以加快搜索的速度;
(2)在作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;
(3)在經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;
(4)在經常需要根據范圍進行搜索的列上創(chuàng)建索引,因為索引已經排序,其指定的范圍是連續(xù)的;
(5)在經常需要排序的列上創(chuàng)建索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;
(6)在經常使用在WHERE子句中的列上面創(chuàng)建索引,加快條件的判斷速度。
(7)在經常使用在order_by 的語句對于有些列不應該創(chuàng)建索引:
(1)對于那些在查詢中很少使用或者參考的列不應該創(chuàng)建索引。
這是因為,既然這些列很少使用到,因此有索引或者無索引,并不能提高查詢速度。相反,由于增加了索引,反而降低了系統(tǒng)的維護速度和增大了空間需求。
(2)對于那些只有很少數據值的列也不應該增加索引。
這是因為,由于這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行占了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,并不能明顯加快檢索速度。
(3)對于那些定義為text, image和bit數據類型的列不應該增加索引。
這是因為,這些列的數據量要么相當大,要么取值很少。
(4)當修改性能遠遠大于檢索性能時,不應該創(chuàng)建索引。
這是因為,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大于檢索性能時,不應該創(chuàng)建索引。
5.什么樣的字段適合建索引
唯一、不為空、經常被查詢的字段
6.MySQL B+Tree索引和Hash索引的區(qū)別?
Hash索引和B+樹索引的特點:
- Hash索引結構的特殊性,其檢索效率非常高,索引的檢索可以一次定位;
- B+樹索引需要從根節(jié)點到枝節(jié)點,最后才能訪問到頁節(jié)點這樣多次的IO訪問;
為什么不都用Hash索引而使用B+樹索引?
- Hash索引僅僅能滿足"=","IN"和""查詢,不能使用范圍查詢,因為經過相應的Hash算法處理之后的Hash值的大小關系,并不能保證和Hash運算前完全一樣;
- Hash索引無法被用來避免數據的排序操作,因為Hash值的大小關系并不一定和Hash運算前的鍵值完全一樣;
- Hash索引不能利用部分索引鍵查詢,對于組合索引,Hash索引在計算Hash值的時候是組合索引鍵合并后再一起計算Hash值,而不是單獨計算Hash值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash索引也無法被利用;
- Hash索引在任何時候都不能避免表掃描,由于不同索引鍵存在相同Hash值,所以即使取滿足某個Hash鍵值的數據的記錄條數,也無法從Hash索引中直接完成查詢,還是要回表查詢數據;
- Hash索引遇到大量Hash值相等的情況后性能并不一定就會比B+樹索引高。
補充:
1.MySQL中,只有HEAP/MEMORY引擎才顯示支持Hash索引。
2.常用的InnoDB引擎中默認使用的是B+樹索引,它會實時監(jiān)控表上索引的使用情況,如果認為建立哈希索引可以提高查詢效率,則自動在內存中的“自適應哈希索引緩沖區(qū)”建立哈希索引(在InnoDB中默認開啟自適應哈希索引),通過觀察搜索模式,MySQL會利用index key的前綴建立哈希索引,如果一個表幾乎大部分都在緩沖池中,那么建立一個哈希索引能夠加快等值查詢。
B+樹索引和哈希索引的明顯區(qū)別是:3.如果是等值查詢,那么哈希索引明顯有絕對優(yōu)勢,因為只需要經過一次算法即可找到相應的鍵值;當然了,這個前提是,鍵值都是唯一的。如果鍵值不是唯一的,就需要先找到該鍵所在位置,然后再根據鏈表往后掃描,直到找到相應的數據;
4.如果是范圍查詢檢索,這時候哈希索引就毫無用武之地了,因為原先是有序的鍵值,經過哈希算法后,有可能變成不連續(xù)的了,就沒辦法再利用索引完成范圍查詢檢索;
同理,哈希索引沒辦法利用索引完成排序,以及l(fā)ike ‘xxx%’ 這樣的部分模糊查詢(這種部分模糊查詢,其實本質上也是范圍查詢);5.哈希索引也不支持多列聯(lián)合索引的最左匹配規(guī)則;
6.B+樹索引的關鍵字檢索效率比較平均,不像B樹那樣波動幅度大,在有大量重復鍵值情況下,哈希索引的效率也是極低的,因為存在所謂的哈希碰撞問題。
7.在大多數場景下,都會有范圍查詢、排序、分組等查詢特征,用B+樹索引就可以了。
7.B樹和B+樹的區(qū)別
- B樹,每個節(jié)點都存儲key和data,所有節(jié)點組成這棵樹,并且葉子節(jié)點指針為nul,葉子結點不包含任何關鍵字信息。
[圖片上傳失敗...(image-7a2a91-1575081433064)]
- B+樹,所有的葉子結點中包含了全部關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點本身依關鍵字的大小自小而大的順序鏈接,所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最?。╆P鍵字。 (而B 樹的非終節(jié)點也包含需要查找的有效信息)
[圖片上傳失敗...(image-338960-1575081433064)]
8.為什么說B+比B樹更適合實際應用中操作系統(tǒng)的文件索引和數據庫索引?
1.B+的磁盤讀寫代價更低
B+的內部結點并沒有指向關鍵字具體信息的指針。因此其內部結點相對B樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說IO讀寫次數也就降低了。
2.B+tree的查詢效率更加穩(wěn)定
由于非終結點并不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。
9.聚集索引和非聚集索引區(qū)別?
聚合索引(clustered index):
聚集索引表記錄的排列順序和索引的排列順序一致,所以查詢效率快,只要找到第一個索引值記錄,其余就連續(xù)性的記錄在物理也一樣連續(xù)存放。聚集索引對應的缺點就是修改慢,因為為了保證表中記錄的物理和索引順序一致,在記錄插入的時候,會對數據頁重新排序。
聚集索引類似于新華字典中用拼音去查找漢字,拼音檢索表于書記順序都是按照a~z排列的,就像相同的邏輯順序于物理順序一樣,當你需要查找a,ai兩個讀音的字,或是想一次尋找多個傻(sha)的同音字時,也許向后翻幾頁,或緊接著下一行就得到結果了。非聚合索引(nonclustered index):
非聚集索引指定了表中記錄的邏輯順序,但是記錄的物理和索引不一定一致,兩種索引都采用B+樹結構,非聚集索引的葉子層并不和實際數據頁相重疊,而采用葉子層包含一個指向表中的記錄在數據頁中的指針方式。非聚集索引層次多,不會造成數據重排。
非聚集索引類似在新華字典上通過偏旁部首來查詢漢字,檢索表也許是按照橫、豎、撇來排列的,但是由于正文中是a~z的拼音順序,所以就類似于邏輯地址于物理地址的不對應。同時適用的情況就在于分組,大數目的不同值,頻繁更新的列中,這些情況即不適合聚集索引。根本區(qū)別:
聚集索引和非聚集索引的根本區(qū)別是表記錄的排列順序和與索引的排列順序是否一致。