MySQL 索引 :哈希索引、B+樹索引、全文索引

文章目錄

  • 索引
    • 引言
    • 常見的索引
  • 哈希索引
    • 自適應哈希索引
  • B+樹索引
    • 聚集索引
    • 非聚集索引
    • 使用方法
    • 聯合索引
    • 最左前綴匹配規則
    • 覆蓋索引
  • 全文索引
    • 使用方法


索引

引言

為什么需要索引?

倘若不使用索引,查找數據時,MySQL必須遍歷整個表。而表越大,查詢的時間則越長,則數據庫的效率也就越低。而索引就類似于書籍的目錄,可以幫助我們快速的定位、檢索到需要的數據行,對提高數據庫的性能有著很大的幫助。

在MySQL中,索引是一種特殊的文件,其中包含著對數據表里所有記錄的引用指針。各類索引有各自的數據結構實現。

索引優缺點

優點:

  • 大大加快了數據檢索的速度
  • 使用要求低,所有的列類型都可以被索引,也就是可以給任意字段設置索引

缺點:

  • 索引需要占用物理空間,建立的索引越多則需要的空間越大
  • 創建和維護索引需要耗費時間,并且時間隨著數據量的增加而增加
  • 當對表中的數據進行增加、刪除、修改的時候,索引也要動態的維護,如果一張表經常需要增刪改,那么有索引的話就降低了數據的更新速度。

適用場景

  • 數據量較大,并且經常對這些列進行查詢。
  • 該數據庫表的插入、修改操作頻率較低。

常見的索引

因為 MySQL 中索引是在 存儲引擎層 實現的,所以并沒有統一的索引標準,換言之:

  • 不同存儲引擎支持的索引類型并不一樣。
  • 而即使多個存儲引擎支持同一種類型的索引,其底層的實現也可能不同。

由于 InnoDB存儲引擎MySQL 數據庫中使用最為廣泛,所以下面的討論主要以 InnoDB 為例。

InnoDB存儲引擎 中,主要支持以下三種常見的索引:B+樹索引、哈希索引、全文索引。


哈希索引

如不了解哈希可移步哈希 :哈希沖突、負載因子、哈希函數、哈希表、哈希桶

原理:通過除留余數法將鍵值轉換為哈希值,并將數據存儲對應的槽中,如果出現了哈希沖突,則使用鏈地址法進行解決,將數據插入對應槽中的鏈表。

由于哈希是直接通過哈希值來將數據映射到對應位置,所以哈希索引對于等值查詢的效率特別高,但是也正因為這個特性,使得哈希查找在面對范圍查找的時候就毫無用武之地了。

自適應哈希索引

InnoDB存儲引擎 會監控對表上各個索引頁的查詢,如果它觀察到建立哈希索引可以帶來速度提升,則會自行建立哈希索引,這也就是 自適應哈希索引。即會自動根據 訪問頻率和模式 來為 熱點數據 建立哈希索引。

哈希索引是數據庫自身自動創建并使用的,人工無法對其進行干預。


B+樹索引

如不了解B+樹可移步數據結構 | B樹、B+樹、B*樹

比起哈希索引,B+樹索引的優勢主要在于排序查找以及區間查找

在數據庫中,B+樹索引可以分為聚集索引(主鍵索引)非聚集索引(輔助索引),它們之間的區別在于葉子節點中存放的是否是一整行的信息(即用戶數據)

PS:葉子節點那一層存儲的是表,而具體的某一個葉子節點才是存儲列。


聚集索引

聚集索引其實就是索引數據在同一個數據結構中。

由于 InnoDB存儲引擎 中表的數據按照主鍵順序存放,所以聚集索引也就是按照每張表的主鍵來構造出一顆B+樹。由于數據真正的排序方式只能有一種,所以在每張表中只能存在著一個聚集索引

這顆B+樹的非葉子節點存放的是數據的索引,而葉子節點存放的即為整張表的行記錄數據,所以我們通常也將葉子節點稱為數據頁,并且每個葉子節點之間用雙向鏈表進行連接。
在這里插入圖片描述
聚集索引對于主鍵的排序查找和范圍查找速度非常快,并且由于葉子節點就是數據,所以只需要查找一次就可以得到結果。


非聚集索引

在這里插入圖片描述
對于 非聚集索引(輔助索引) 來說,葉子節點并不包含行記錄的全部數據,而是包含了主鍵的值。

也就是說,我們需要在非聚集索引中查找到主鍵,再通過主鍵聚集索引中查找到具體的值,也就是需要兩次查找。所以非聚集索引其實也就是一個二級索引

在這里插入圖片描述
基于以上特性,由于輔助索引的存在并不會影響數據聚集索引中的存在方式,因此每張表中可以有多個輔助索引。


使用方法

創建主鍵約束(PRIMARY KEY)、唯一約束(UNIQUE)、外鍵約束(FOREIGN KEY)時,會自動創建對應列的索引。

查看索引

SHOW INDEX FROM 表名 

創建

CREATE INDEX 索引名 ON 表名(字段名)
或者
ALTER TABLE 表名 ADD {KEY | INDEX} 索引名

刪除

DROP INDEX 索引名 ON 表名

聯合索引

聯合索引即對表上的多個列進行索引:
在這里插入圖片描述
聯合索引和普通的B+樹不同的地方在于它具有多個鍵值,鍵值按照從左往右的優先級以此對鍵值的大小進行排序,例如:上圖有兩個鍵值,首先會先按照第一個鍵值的大小進行排序,當第一個鍵相同時,再按照第二個鍵的大小進行排序。

因為以上特性,聯合索引具有最左前綴匹配規則,當不滿足規則時則不會使用聯合索引,而是進行全索引掃描。


最左前綴匹配規則

就以上述數據進行舉例,此時以鍵值 (a, b) 構建聯合索引

SELECT * FROM TABLE WHERE a = xxx AND b = xxx 、
SELECT * FROM TABLE WHERE a = xxx 
SELECT * FROM TABLE WHERE b = xxx 

對于以上幾條查詢語句來說,雖然看起來差不多,但是效率卻大相徑庭。

對于前兩句來說,它們是可以使用聯合索引的,因為無論是按照 a 作為條件,或者是 ab 作為條件。因為前面也說過了,聯合索引的排序是按照從左往右優先的,所以當前兩句都是優先根據 a 進行索引搜索,不會出現問題。

但對于 b=xxx 則無法適用以上性質,因為在聯合索引中,后面的主鍵只有在前面的主鍵相同時才會具有有序性,而單獨適用它的時候顯然數據是無序的,所以這時只能進行全索引掃描

對于范圍查找也是這么一個道理,假設此時聯合索引的主鍵為(a, b, c)

SELECT * FROM TABLE WHERE a > 3 AND b > 3
SELECT * FROM TABLE WHERE a > 3 AND b > 3 AND c > 3 
SELECT * FROM TABLE WHERE a > 3 AND c > 3

同樣按照上面的規則,前兩種查詢都可以適用聯合索引,因為其遵循了從左至右的匹配原則,而第三條因為跳過了 b,此時的數據是無序的,無法適用索引。


覆蓋索引

覆蓋索引即從輔助索引中就可以得到查詢的記錄,而不需要查詢聚集索引中的記錄。使用覆蓋索引的一個好處就是由于輔助索引中不包含整行的所有記錄,所以它的大小要遠遠小于聚集索引,因此可以減少大量的 I/O 操作。

由于輔助索引中葉子節點存放的數據就是主鍵,所以當我們要查找主鍵,或者通過主鍵來統計數量的時候,就可以使用覆蓋索引來完成。


全文索引

在之前版本中只有 InnoDB 并不支持全文檢索,而在 InnoDB1.2.x 版本之后,InnoDB 也加入了全文檢索的功能。

全文索引即根據部分段落、句、詞從數據庫中查詢除全文的技術,即根據部分查詢詞獲取對應的文檔。

主要依據倒排索引這一數據結構來實現,這一數據結構通常也在搜索引擎中進行使用。

這里就簡要的介紹一下 InnoDB 中的倒排索引。其擁有兩種表現形式:

  • inverted file index(倒排文件索引)
    表現形式 {單詞, 單詞所在的文檔ID)
  • full inverted index(全文倒排索引)
    表現形式{單詞, (單詞所在文檔ID,在具體文檔的位置)

例如我們存在以下數據:
在這里插入圖片描述
并將其構建成 inverted file index(倒排文件索引) 的形式:
在這里插入圖片描述
此時我們就建立起了各個單詞與其對應文檔的一個映射關系。

接著建立 full inverted index(全文倒排索引)

在這里插入圖片描述
此時在之前的基礎上,我們不僅確定了單詞所在的文章,還確定了其所在文章中的對應位置,雖然比起 inverted file index來 說更加復雜,占據的空間也更多,但是卻能更好的定位數據,并且擴充一些其它的搜索特性。


使用方法

創建全文索引

CREATE FULLTEXT INDEX 索引名 ON 表名(字段名);

查找方法

MATCH(要匹配的列) AGAINST(要查找的內容) 
  1. 自然語言查詢(Natural Language),即普通的包含關鍵詞的搜索,例如:
SELECT * FROM (表名) WHERE MATCH(匹配列) AGAINST(查詢內容)
  1. Boolean,這個模式允許使用 IN BOOLEAN MODE修飾符 來進行全文檢索,當使用該修飾符時,查詢字符串的前后字符都會有特殊含義。例如 +- 分別代表了該單詞必須出現或者一定沒出現。

這句查詢即匹配包含 查詢詞1 并且不包含 查詢詞2 的結果:

SELECT * FROM 表名 
WHERE MATCH (要匹配的列) AGAINST ('+查詢詞1 -查詢詞2' IN BOOLEAN MODE);

該模式所有選項如下:
在這里插入圖片描述
全文查詢的結果依據相關度進行降序排序,相關度計算依據如下:

  • 查詢詞是否在文檔中出現過
  • 查詢詞在文檔中出現的次數
  • 查詢詞在索引列中的數量
  • 包含查詢詞的文檔數

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443750.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443750.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443750.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

服裝店怎么引流和吸引顧客 服裝店鋪收銀系統來配合

實體店的同城引流和經營是實體經濟的一個重要的一環,今天我們來分享服裝行業的實體店鋪怎么引流和吸引、留住顧客,并實現復購。大家點個收藏,不然劃走就再也找不到了,另外可以點個關注,下次有新的更好的招,…

約瑟夫環(丟手絹問題)

文章目錄問題描述思路代碼實現問題描述 有 1~N 個數字,從 1~m 依次報數,數到 m 的數字要被刪掉,求最后剩下的數字是? 思路 第一次報數第二次報數1n-m12n-m2……m-2n-2m-1n-1m被刪掉了m11m22……n-1n-1-mnn-m 通過上面的表格&…

MySQL 鎖的相關知識 | lock與latch、鎖的類型、簡談MVCC、鎖算法、死鎖、鎖升級

文章目錄lock與latch鎖的類型MVCC一致性非鎖定讀(快照讀)一致性鎖定讀(當前讀)鎖算法死鎖鎖升級lock與latch 在了解數據庫鎖之前,首先就要區分開 lock 和 latch。在數據庫中,lock 和 latch 雖然都是鎖&…

Hibernate使用原生SQL適應復雜數據查詢

HQL盡管容易使用,但是在一些復雜的數據操作上功能有限。特別是在實現復雜的報表統計與計算,以及多表連接查詢上往往無能為力,這時可以使用SQL(Native SQL)實現HQL無法完成的任務。 1、使用SQL查詢 使用SQL查詢可以通過…

MySQL 存儲引擎 | MyISAM 與 InnoDB

文章目錄概念innodb引擎的4大特性索引結構InnoDBMyISAM區別表級鎖和行級鎖概念 MyISAM 是 MySQL 的默認數據庫引擎(5.5版之前),但因為不支持事務處理而被 InnoDB 替代。 然而事物都是有兩面性的,InnoDB 支持事務處理也會帶來一些…

MySQL 事務 | ACID、四種隔離級別、并發帶來的隔離問題、事務的使用與實現

文章目錄事務ACID并發帶來的隔離問題幻讀(虛讀)不可重復讀臟讀丟失更新隔離級別Read Uncommitted (讀未提交)Read Committed (讀已提交)Repeatable Read (可重復讀)Serializable (可串行化)事務的使用事務的實現Redoundo事務 事務指邏輯上的一組操作。 …

MySQL 備份與主從復制

文章目錄備份主從復制主從復制的作用備份 根據備份方法的不同,備份可劃分為以下幾種類型: 熱備(Hot Backup) : 熱備指的是在數據庫運行的時候直接備份,并且對正在運行的數據庫毫無影響,這種方法在 MySQL 官方手冊中又…

C++ 流的操作 | 初識IO類、文件流、string流的使用

文章目錄前言IO頭文件iostreamfstreamsstream流的使用不能拷貝或對 IO對象 賦值條件狀態與 iostate 類型輸出緩沖區文件流fstream類型文件模式文件光標函數tellg() / tellp()seekg() / seekp()向文件存儲內容/讀取文件內容string流istringstreamostringstream前言 我們在使用 …

Hibernate 更新部分更改的字段 hibernate update

Hibernate 中如果直接使用 Session.update(Object o);或則是Session.updateOrUpdate(Object o); 會把這個表中的所有字段更新一遍。 如: ExperClass4k e new ExperClass4k(); e.setTime(time); e.setQ_num(q_num); e.setK(k); if (str "finch_fix")…

C++ 類的行為 | 行為像值的類、行為像指針的類、swap函數處理自賦值

文章目錄概念行為像值的類行為像指針的類概念引用計數動態內存實現計數器類的swap概念swap實現自賦值概念 行為像值的類和行為像指針的類這兩種說法其實蠻拗口的,這也算是 《CPrimer》 翻譯的缺點之一吧。。。 其實兩者的意思分別是: 行為像值的類&am…

C++ 右值引用 | 左值、右值、move、移動語義、引用限定符

文章目錄C11為什么引入右值?區分左值引用、右值引用move移動語義移動構造函數移動賦值運算符合成的移動操作小結引用限定符規定this是左值or右值引用限定符與重載C11為什么引入右值? C11引入了一個擴展內存的方法——移動而非拷貝,移動較之拷…

且談關于最近軟件測試的面試

前段時間有新的產品需要招人,安排和參加了好幾次面試,下面就談談具體的面試問題,在面試他人的同時也面試自己。 面試問題是參與面試同事各自設計的,我也不清楚其他同事的題目,就談談自己設計的其中2道題。 過去面試總是…

C++ 多態 | 虛函數、抽象類、虛函數表

文章目錄多態虛函數重寫重定義(參數不同)協變(返回值不同)析構函數重寫(函數名不同)final和override重載、重寫、重定義抽象類多態的原理虛函數常見問題解析虛函數表多態 一種事物,多種形態。換…

C++ 運算符重載(一) | 輸入/輸出,相等/不等,復合賦值,下標,自增/自減,成員訪問運算符

文章目錄輸出運算符<<輸入運算符>>相等/不等運算符復合賦值運算符下標運算符自增/自減運算符成員訪問運算符輸出運算符<< 通常情況下&#xff0c;輸出運算符的第一個形參是一個 非常量ostream對象的引用 。之所以 ostream 是非常量是因為向流寫入內容會改變…

C++ 重載函數調用運算符 | 再探lambda,函數對象,可調用對象

文章目錄重載函數調用運算符lambdalambda等價于函數對象lambda等價于類標準庫函數對象可調用對象與function可調用對象function函數重載與function重載函數調用運算符 函數調用運算符必須是成員函數。 一個類可以定義多個不同版本的調用運算符&#xff0c;互相之間應該在參數數…

C++ 運算符重載(二) | 類型轉換運算符,二義性問題

文章目錄類型轉換運算符概念避免過度使用類型轉換函數解決上述問題的方法轉換為 bool顯式的類型轉換運算符類型轉換二義性重載函數與類型轉換結合導致的二義性重載運算符與類型轉換結合導致的二義性類型轉換運算符 概念 類型轉換運算符&#xff08;conversion operator&#…

Tomcat中JVM內存溢出及合理配置

Tomcat本身不能直接在計算機上運行&#xff0c;需要依賴于硬件基礎之上的操作系統和一個Java虛擬機。Tomcat的內存溢出本質就是JVM內存溢出&#xff0c;所以在本文開始時&#xff0c;應該先對Java JVM有關內存方面的知識進行詳細介紹。 一、Java JVM內存介紹 JVM管理兩種類型的…

俄羅斯農民乘法 | 快速乘

文章目錄概念概念 俄羅斯農民乘法經常被用于兩數相乘取模的場景&#xff0c;如果兩數相乘已經超過數據范圍&#xff0c;但取模后不會超過&#xff0c;我們就可以利用這個方法來拆位取模計算貢獻&#xff0c;保證每次運算都在數據范圍內。 A 和 B 兩數相乘的時候我們如何利用加…

Linux網絡編程 | socket選項設定 及 網絡信息API

文章目錄讀取和設置 socket 選項SO_REUSEADDRSO_RCVBUF 和 SO_SNDBUFSO_RCVLOWAT 和 SO_SNDLOWATSO_LINGER 選項網絡信息APIgethostbyname 和 gethostbyaddrgetservbyname 和 getservbyportgetaddrinfogetnameinfo讀取和設置 socket 選項 正如 fcntl 系統調用是控制文件描述符…

Linux | 高級I/O函數

文章目錄創建文件描述符的函數pipe函數dup函數、dup2函數讀取或寫入數據readv函數、writev函數零拷貝sendfile函數splice函數tee函數進程間通信——共享內存mmap函數 和 munmap函數控制文件描述符fcntl函數創建文件描述符的函數 pipe函數 不再贅述&#xff0c;詳情見我的另一…