慢查詢引發對mysql索引的探索

目錄

一、索引分類

1.1 聚簇索引結構

1.2 非聚簇索引(二級索引)

1.3 主鍵索引

1.4 唯一索引

1.5 普通索引

1.6 前綴索引

1.7 聯合索引

1.8 索引下推

1.9 索引區分度

二、優化索引的方法

2.1 索引的特點

2.2 適合創建索引的情況

2.3 不適合創建索引的情況

2.4?優化索引的方法


慢查詢的原因之一就是索引使用不當,本文對索引的本質和結構來剖析如何使用索引

一、索引分類

索引是數據的目錄,是一種數據結構,為了快速檢索與查找數據

索引分類:

維度類別
數據結構B+tree索引、Hash索引、Full-text索引
物理存儲聚簇索引(主鍵索引)、二級索引(輔助索引)
字段特性主鍵索引、唯一索引、普通索引、前綴索引
字段個數單列索引、聯合索引

MySQL 存儲引擎默認是InnoDB,在InnoDB中必須有聚簇索引,這是由于InnoDB存儲引擎的索引結構B+tree有關系。

在創建表時,會創建一個聚簇索引:

  • 如果有主鍵,默認會使用主鍵作為聚簇索引的索引鍵(key);
  • 如果沒有主鍵,就選擇第一個不包含 NULL 值的唯一列作為聚簇索引的索引鍵(key)
  • 如果上面兩個都沒有,InnoDB 將自動生成一個隱式自增 id 列作為聚簇索引的索引鍵(key)

1.1 聚簇索引結構

如圖:B+樹是一個多叉樹,葉子節點存放數據,非葉子節點存放索引,每個節點都是按照主鍵順序存放,葉子節點中的數據包括主鍵索引、數據、上一個節點的指針和下一個結點的指針

根據上面的圖分析 select * from product where id=5

第一步:將id=5與根節點索引(1,10,20)比較,5在(1,10)之間,索引搜索找到第二層節點

第二步:將id=5與第二層節點(1,4,7)比較,5在(4,7)之間,找到第三層索引

第三步:在(4,5,6)之間查找,找到索引值=5的行數據

InnoDB的索引和數據都是存儲在硬盤中的,每次讀取數據都要進行一次硬盤IO操作,上述步驟一共進行了3個IO操作。

1.2 非聚簇索引(二級索引)

非聚簇索引,例如product值是二級索引,則用product創建的順序索引結構如下:

其中非葉子節點是product索引值,而葉子節點放的是product索引值與主鍵數據

分析:select * from product where product = '0002';?

第一步:在非聚簇索引中知道product=0002的主鍵索引值,id=2

第二步:回表查詢,在聚簇索引中根據id=2查詢行數據

回表:當查詢使用非聚集索引(secondary index)時,需要先通過索引找到對應的數據行主鍵,然后再根據主鍵去聚集索引(primary index)中獲取完整數據行的過程。

非回表查詢:

select id?from product where product = '0002';?

查詢的id就在非聚簇索引中,不需要回表去主鍵索引中查詢,這種在二級索引中就可以查到結果的過程叫覆蓋索引,查一個B+樹就可以找到。

1.3 主鍵索引

建立在主鍵字段上,創建表的時候一起創建,一個表只有一個主鍵索引,主鍵索引列不能為空值

CREATE TABLE table_name{...PRIMARY KEY(id) USING BTREE
}

1.4 唯一索引

與主鍵索引不同的地方,一個表可以有多個唯一索引,唯一索引允許索引列有空值,但是唯一索引列的值必須唯一。

//創建表時創建索引
CREATE TABLE table_name(...UNIQUE KEY(column1,column2)
);//建表后增加索引
CREATE UNIQUE INDEX index_name 
ON table_name(column1,column2)或者
ALTER TABLE table_name 
ADD UNIQUE (column1, column2);

1.5 普通索引

建立在普通的字段上,不要求字段值非空,也不要求字段值唯一

//創建表時創建索引
CREATE TABLE table_name(...INDEX(column1,column2)
);//建表后增加索引
CREATE INDEX index_name 
ON table_name(column1,column2)或者
ALTER TABLE table_name 
ADD INDEX (column1, column2);

1.6 前綴索引

對字符類型字段的前幾個字符創建索引,目的是為了節省索引所占的存儲空間,提高查詢效率

1.7 聯合索引

由多個字段組成的索引為聯合索引,例如productId和productName兩個字段創建的索引,其索引結構如下:

聯合索引的非葉子節點是用productId和name做值,索引先按照productId排序,productId相同時按照name排序,所以聯合索引需要滿足最左匹配原則,如果不滿足,則該聯合索引就會失效,無法利用索引提高查詢效率。

如果語句where name=ipad8,則無法使用聯合索引(productId,name),因為name字段是局部有序,全局無序的,利用索引的前提是索引是全局有序的。

舉例說明,哪些情況聯合索引生效,聯合索引(a,b)

語句索引說明
select * from table where a>1 and b=2a字段用到了聯合索引,b字段沒有用到a字段是有序的,可以定位到符合a>1的紀錄,但是b是無序的
select * from table where a>=1 and b=2a,b字段都用到了聯合索引a>=1索引可以很快定位到a=1的紀錄,b=2可以將索引定位到a=1,b=2的紀錄,然后往后掃描
select * from table where a between 2 and 8 and b=2a,b字段都用到了聯合索引between and相當于a>=2 and a<=8,b=2可以進一步縮小索引掃描的行數
select * from table where a like 'j%' and b=2a,b字段都用到了聯合索引當索引a字段值為‘j%’時,b=2可以減少掃描的二級索引紀錄行數

1.8 索引下推

select * from table where a>1 and b=2,對于聯合索引(a,b),只有a字段用到了索引,那b字段是回表查詢后進行判斷呢還是在二級索引中判斷呢?

mysql5.6后,引入了索引下推,可以在二級索引中之間判斷其它字段是否滿足條件,減少回表的次數,例如在二級索引中查詢出a>2的紀錄之后,會在二級索引中包含的字段b進行判斷是否滿足b=2

1.9 索引區分度

建立聯合索引時,需要將區分度大的字段排在前面,區分度小的排在后面,區分度越大過濾的數據越多,區分度=一個字段值去重后的個數/該字段總數

二、優化索引的方法

2.1 索引的特點

優點:提高查詢效率

缺點:占用物理空間,數量越大占用越多;創建和維護索引占用時間,索引越大占用時間越多;增加表增刪改的效率,因為每次更新都要動態維護索引數據。

2.2 適合創建索引的情況

  1. 字段有唯一性限制;
  2. where中的字段,如果查詢條件是多個字段,可以創建聯合索引;
  3. group by與order by中的字段,因為索引是排好序的,不需要重新排序;

2.3 不適合創建索引的情況

  1. 字段區分度低的,例如性別,優化器會在區分度很低時,放棄索引,采用全表掃描;
  2. where 、group by、order by中用不到的字段,索引的作用是快速定位,否則只會占用空間;
  3. 經常更新的字段不適合創建索引,會增加維護索引的成本;
  4. 數據量很少時不適合創建索引,數據量很少時全表掃描會更快;

2.4?優化索引的方法

  1. 前綴索引優化:大字符做索引時,用前綴索引,減少索引字段大小,提高索引頁中存儲的索引數量
  2. 覆蓋索引優化:對于查詢的字段可以創建聯合索引,直接在二級索引中查詢出所有的數據,不需要回表查詢主鍵索引,減少IO操作
  3. 主鍵索引自增:自增索引在增加數據時,直接開辟新的頁存儲數據,不需要移動其他的數據,否則會導致頁分裂,造成內存碎片,索引結構不緊湊,影響查詢效率。
  4. 防止索引失效:
  • 不符合最左匹配原則:例如like '%xx'或者like '%xx%'
  • 對索引列進行計算、函數、類型轉換
  • OR條件,只有一個條件有索引時,也會索引失效

參考:索引常見面試題 | 小林coding

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

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

相關文章

啟用不安全的HTTP方法

背景&#xff1a; 今天被安全檢測出一個這樣的問題&#xff1a;啟用不安全的HTTP方法。DELETE方法是用來調試web服務器連接的http方式&#xff0c;支持該方式的服務器文件可能被非法刪除&#xff1b;PUT方法用來向服務器提交文件&#xff1b;TRACE方法本用于客戶端測試到服務器…

fvcom 水深文件dep制作

fvcom 水深文件dep制作 fvcom 水深文件dep制作20250630 本次案例網格和水深展示 vv image Figure 1 Model domain 本次制作其它驅動文件的輸入文件為yellowsea.2dm 格式2dm; 文件內容格式詳細介紹參考&#xff1a; https://www.xmswiki.com/wiki/SMS:2D_Mesh_Files_*.2dm …

ViewModel是EventFlow-State映射

ViewModel負責組裝界面狀態State。引發State變換的原因有很多&#xff0c;比如用戶點擊某個按鈕&#xff0c;一次網絡請求受到應答&#xff0c;一次本地數據庫查詢返回結果等等。因此ViewModel是根據各種事件生成State的對象&#xff0c;換句話說&#xff0c;是一個從多個事件流…

javaweb Day2

PreparedStatement作用: 預編譯SQL語句并執行: 預防SQL注入問題 SQL注入:SQL注入是通過操作輸入來修改事先定義好的SQL語句&#xff0c;用以達到執行代碼對服務器進行攻擊的方法。

Java項目:基于SSM框架實現的中學教學管理系統【ssm+B/S架構+源碼+數據庫+畢業論文+開題報告】

摘 要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本景海中學教學管理系統就是在這樣的大環境下誕生&#xff0c;其可以幫助管理者在短時間內處理完畢龐大的數據…

JVM調優實戰 Day 15:云原生環境下的JVM配置

【JVM調優實戰 Day 15】云原生環境下的JVM配置 文章標簽 jvm調優, 云原生, Java性能優化, JVM參數配置, 容器化部署, Kubernetes, Docker, JVM在云原生中的應用 文章簡述 隨著云原生技術的普及&#xff0c;Java 應用越來越多地運行在容器&#xff08;如 Docker&#xff09;和…

數據結構day7——文件IO

一、標準 IO 的起源與概念 標準 IO&#xff08;Standard Input/Output&#xff09;是由 Dennis Ritchie 在 1975 年設計的一套 IO 庫&#xff0c;后來成為 C 語言的標準組成部分&#xff0c;并被 ANSI C 所采納。它是對底層文件 IO 的封裝&#xff0c;提供了更便捷、可移植的文…

6.Docker部署ES+kibana

部署ES&#xff08;Elasticsearch&#xff09;kibana 1.ES暴露的端口很多 2.ES十分消耗內存 3.ES的數據一般需要掛載出去&#xff0c;放在安全目錄&#xff08;掛載) elastic 前往官方手冊 1.下載運行elasticsearch的 docker run -d --name elasticsearch --net somenet…

使用mysqldump對mysql數據庫進行備份

目錄 1軟件說明 2語法格式 3備份流程 3.1只備份指定數據庫中表和數據 3.1.1準備目錄 3.1.2備份db1數據庫里面的所有表信息 3.1.3還原備份 3.2備份數據庫結構 3.2.1備份db1數據庫的結構和數據 3.2.2還原數據庫 3.3備份所有數據庫 3.3.1備份數據庫 3.3.2還原數據庫 1…

vue3路由跳轉打開新頁面

Vue3 路由跳轉打開新頁面的方法 在 Vue3 中&#xff0c;有幾種方法可以實現路由跳轉時打開新頁面&#xff1a; 1. 使用 router.resolve 方法 import { useRouter } from vue-routerconst router useRouter()const openNewPage (path) > {const resolved router.resolv…

SeaTunnel 社區 2 項目中選“開源之夏 2025”,探索高階數據集成能力!

Apache SeaTunnel 社區在“開源之夏 2025”中再傳捷報&#xff0c;共有兩個項目成功入選&#xff0c;聚焦于 Flink CDC schema 支持與元數據管理的生態擴展方向&#xff0c;體現出 SeaTunnel 在實時數據集成和平臺化能力構建上的深入布局。 中選項目與學生如下&#xff1a; 《…

Neo4j無法建立到 localhost:7474 服務器的連接出現404錯誤

一、確認中文路徑問題&#xff08;核心原因&#xff09; 安裝路徑包含中文&#xff0c;可能導致 Windows 命令行或 Neo4j 解析路徑時出錯。 解決方法&#xff1a; 重新安裝 Neo4j 到英文路徑&#xff08;推薦&#xff09;&#xff1a; 將 Neo4j 解壓或安裝到不含中文的目錄&a…

鋰離子電池均衡拓撲綜述

鋰離子電池均衡拓撲綜述 一、引言 鋰離子電池因其高能量密度、長循環壽命等優點&#xff0c;在電動汽車、儲能系統等領域得到了廣泛應用。然而&#xff0c;電池組在使用過程中&#xff0c;由于電池個體差異、充放電管理等因素&#xff0c;會出現荷電狀態&#xff08;SOC&…

[面試] 手寫題-淺拷貝,深拷貝

淺拷貝 // 淺拷貝 function shallow(obj) {const newObj {}for (const key in obj) {// 保證 key 不是原型的屬性if (obj.hasOwnProperty(key)) {newObj[key] obj[key]}}return newObj }深拷貝 遞歸 O(n^2) // 深拷貝 function deepClone(obj {}) {// 如果傳入的是 null&am…

BehaviorTree.ROS2安裝記錄

坑比庫&#xff0c; 首先 git clone https://github.com/BehaviorTree/BehaviorTree.ROS2.git 依賴 git clone https://github.com/PickNikRobotics/cpp_polyfills.git git clone https://github.com/PickNikRobotics/RSL.git git clone https://github.com/PickNikRobotics/…

Vue基礎(19)_Vue內置指令

我們學過的vue內置指令&#xff1a; v-bind&#xff1a;單向綁定解析表達式&#xff0c;可簡寫為&#xff1a;:xxx v-model&#xff1a;雙向數據綁定 v-for&#xff1a;遍歷數組/對象/字符串 v-on&#xff1a;綁定事件監聽&#xff0c;可簡寫為 v-if&#xff1a;條件渲染(動態控…

排列組合初步

什么是排列組合 排列組合是計數問題&#xff0c;順序不同且值相同算兩種方案是排列&#xff0c;順序不同且值相同算一種方案是組合。 暴力枚舉方案能算出方案數&#xff0c;太耗時&#xff0c;運用加法原理和乘法原理可降低時間復雜度。先將原問題拆解成子問題&#xff0c;根…

SQL調優方案對比與最佳實踐

問題背景介紹 在大型互聯網或企業級應用中&#xff0c;數據庫往往成為系統性能的瓶頸。隨著數據量和并發量的增長&#xff0c;單一的 SQL 查詢可能出現響應遲緩、鎖等待、全表掃描等性能問題。為保證系統的穩定性和用戶體驗&#xff0c;需要對 SQL 查詢做深入的調優。常見的調…

Terraform Helm:微服務基礎設施即代碼

&#x1f680; Terraform & Helm&#xff1a;微服務基礎設施即代碼 &#x1f4da; 目錄 &#x1f680; Terraform & Helm&#xff1a;微服務基礎設施即代碼1. 引言 &#x1f680;2. 環境與依賴 &#x1f9f0;3. 架構示意 &#x1f3d7;?4. Terraform 定義云資源 &…

清理 Docker 緩存占用

Docker 緩存主要包括未使用的鏡像、容器、卷和網絡等資源。清理緩存可以提高磁盤空間&#xff0c;線上升級次數比較多的話&#xff0c;服務器中Docker緩存會非常嚴重&#xff0c;做下清理瘦身會有意想不到的效果 清理未使用的鏡像 運行以下命令刪除未被任何容器引用的鏡像&…