字首索引 mysql索引總結

2021-10-13 15:58:05 字數 3055 閱讀 9034

擊上方藍色「程式設計師白楠楠」,選擇「設為星標」

出處:資料結構

常見的資料結構有 雜湊表、有序陣列和搜尋樹

雜湊表是一種以鍵 - 值(key-value)儲存資料的結構,我們只要輸入待查詢的值即 key, 就可以找到其對應的值即 value。雜湊的思路很簡單,把值放在陣列裡,用乙個雜湊函式 把 key 換算成乙個位置,然後把 value 放在陣列的對應位置

不可避免地,多個 key 值經過雜湊函式的換算,會出現同乙個值的情況。處理這種情況的 一種方法是,拉出乙個鍊錶

雜湊表這種結構適用於只有等值查詢的場景

有序陣列在等值查詢和範圍查詢場景中的效能就都非常優秀

如果僅僅看查詢效率,有序陣列就很好。但是,在需要更新資料的時候就 麻煩了,你往中間插入乙個記錄就必須得挪動後面所有的記錄,成本太高

有序陣列索引只適用於靜態儲存引擎

二叉搜尋樹的特點是:每個節點的左兒子小於父節點,父節點又小於右兒子

當然為了維持 o(log(n)) 的查詢複雜度,你就需要保持這棵樹是平衡二叉樹。為了做這個 保證,更新的時間複雜度也是 o(log(n))

二叉樹是搜尋效率最高的,但是實際上大多數的資料庫儲存卻並不使用二叉樹。其原因是,索引不止存在記憶體中,還要寫到磁碟上

為了讓乙個查詢盡量少地讀磁碟,就必須讓查詢過程訪問盡量少的資料塊。那麼,我們就不應該使用二叉樹,而是要使用「n 叉」樹。這裡,「n 叉」樹中的「n」取決於資料塊的大小

n 叉樹由於在讀寫上的效能優點,以及適配磁碟的訪問模式,已經被廣泛應用在資料庫引擎中了

innodb 的索引模型

在 innodb 中,表都是根據主鍵順序以索引的形式存放的,這種儲存方式的表稱為索引組織表。innodb 使用了 b+ 樹索引模型,所以資料都是儲存在 b+ 樹中的

每乙個索引在 innodb 裡面對應一棵 b+ 樹

根據葉子節點的內容,索引型別分為主鍵索引和非主鍵索引

主鍵索引的葉子節點存的是整行資料。在 innodb 裡,主鍵索引也被稱為聚簇索引

非主鍵索引的葉子節點內容是主鍵的值。在 innodb 裡,非主鍵索引也被稱為二級索引

基於非主鍵索引的查詢需要多掃瞄一棵索引樹(回表)。因此,我們在應用中應該盡量 使用主鍵查詢

索引維護

b+ 樹為了維護索引有序性,在插入新值的時候需要做必要的維護

如果新插入的 id 值比原來的小,就相對麻煩了,需要邏輯上挪動後面的資料,空出位置

而更糟的情況是,如果所在的資料頁已經滿了,根據 b+ 樹的演算法,這時候需要申請 乙個新的資料頁,然後挪動部分資料過去。這個過程稱為頁**。在這種情況下,效能自然會受影響。

除了效能外,頁**操作還影響資料頁的利用率。原本放在乙個頁的資料,現在分到兩個頁中,整體空間利用率降低大約 50%。

當然有**就有合併。當相鄰兩個頁由於刪除了資料,利用率很低之後,會將資料頁做合 並。合併的過程,可以認為是**過程的逆過程

自增主鍵的插入資料模式,正符合了我們前面提到的遞增插入的場景。每次插 入一條新記錄,都是追加操作,都不涉及到挪動其他記錄,也不會觸發葉子節點的**。

而有業務邏輯的字段做主鍵,則往往不容易保證有序插入,這樣寫資料成本相對較高

主鍵長度越小,普通索引的葉子節點就越小,普通索引占用的空間也就越小

所以,從效能和儲存空間方面考量,自增主鍵往往是更合理的選擇

有沒有什麼場景適合用業務字段直接做主鍵的呢?還是有的。比如,有些業務的場景需求 是這樣的:

只有乙個索引;

該索引必須是唯一索引。

這就是典型的 kv 場景

覆蓋索引

如果執行的語句是 select id from t ,這時只需要查 id 的 值,而 id 的值已經在 k 索引樹上了,因此可以直接提供查詢結果,不需要回表。也就是說,在這個查詢裡面,索引 k 已經「覆蓋了」我們的查詢需求,我們稱為覆蓋索引

由於覆蓋索引可以減少樹的搜尋次數,顯著提公升查詢效能,所以使用覆蓋索引是乙個常用的效能優化手段

索引下推

滿足最左字首原則的時候,最左字首可以用於在索引中定位記錄。這時,你可能要問,那些不符合最左字首的部分,會怎麼樣呢?

mysql 5.6 引入的索引下推優化, 可以在索引遍歷過 程中,對索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數

最左字首原則

不只是索引的全部定義,只要滿足最左字首,就可以利用索引來加速檢索

在建立聯合索引的時候,如何安排索引內的字段順序?

這裡我們的評估標準是,索引的復用能力。因為可以支援最左字首,所以當已經有了 (a,b) 這個聯合索引後,一般就不需要單獨在 a 上建立索引了。因此,第一原則是,如果通過調整順序,可以少維護乙個索引,那麼這個順序往往就是需要優先考慮採用的

字首索引

利用最左字首原則可以定義字串的一部分作為索引。預設地,如果你建立索引的語句不指定字首長度,那麼索引就會包含整個字串

但,這同時帶來的損失是,可能會增加額外的記錄掃瞄次數,因為索引相同需要進一步比較

使用字首索引,定義好長度,就可以做到既節省空間,又不用額外增加太多的查 詢成本

可以通過統計索引上有多少個不同的值來判斷要使用多長的字首,從而減少掃瞄次數

字首索引對覆蓋索引的影響

使用字首索引就用不上覆蓋索引對查詢效能的優化了,這也是你在選擇是否使用字首索引時需要考慮的乙個因素

倒序儲存和hash儲存

對於類似於郵箱這樣的字段來說,使用字首索引的效果可能還不錯。但是,遇到字首的區 分度不夠好的情況時,我們要怎麼辦呢?

第一種方式是使用倒序儲存。如果你儲存身份證號的時候把它倒過來存

第二種方式是使用 hash 字段。你可以在表上再建立乙個整數字段,來儲存身份證的校驗碼,同時在這個欄位上建立索引

mysql 建字首索引 MySQL 字首索引

檢視出現頻率 select count as cnt,city from sakila.city demo group by city order by cnt desc limit 10 1.select count distinct city count from sakila.city dem...

mysql 字首索引 語法 MySQL 字首索引

索引字首 使用 字串列的索引規範中的語法,您可以建立僅使用列首字元的索引 以這種方式僅索引列值的字首可以使索引檔案小得多。為a 或 column 編制索引時 必須為索引指定字首長度。例如 col name n nblobtext create table test blob col blob,ind...

mysql 字首索引 語法 mysql字首索引

應用場景 資料庫裡有個位址 address 字段,型別為varchar 100 業務決定了要經常根據address來進行查詢。確定選擇性 sql select count distinct address count as selectivity from info selectivity 0.87...