MySQL 表 t1 建立聯合索引 (a, b, c),在 where a < ? and b > ? and c < ? 中哪些索引生效

文章目錄

  • 聯合索引 abc 均范圍掃描時的索引生效情況
    • 無回表 + 表數據量非常少
    • 無回表 + 表數據量多
    • 有回表
    • 總結

聯合索引 abc 均范圍掃描時的索引生效情況

場景:表 t1 建立聯合索引 (a, b, c),在 where a < ? and b > ? and c < ? 中哪些索引生效。

無回表 + 表數據量非常少

場景準備:聯合索引 (a, b, c) 已經是完整的數據記錄,可以使用覆蓋索引,表數據量非常少的意思是只有 0 或 1 條記錄(測試發現)。

DROP TABLE IF EXISTS t1;CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY,a INT NOT NULL,b INT NOT NULL,c INT NOT NULL,INDEX idx_a_b_c(a, b, c)
);drop procedure if exists GenerateTestData;DELIMITER //CREATE PROCEDURE GenerateTestData()
BEGINDECLARE i INT DEFAULT 0;WHILE i < 1 DOINSERT INTO t1 (a, b, c)VALUES (FLOOR(1 + RAND() * 100),  -- 生成 1-100 的隨機整數FLOOR(1 + RAND() * 100),FLOOR(1 + RAND() * 100));SET i = i + 1;END WHILE;
END //DELIMITER ;call GenerateTestData;

查看當前表信息:

SELECT * FROM t1;

image-20250326131640941

接著分析此場景下的聯合索引生效情況:

EXPLAIN
SELECT *
FROM t1
WHERE a < 2 AND b > 3 AND c < 5; 

image-20250326131823785

分析:

  • type = index 表示可以使用覆蓋索引,但需要掃描全部的索引記錄。
  • key = idx_a_b_c 表示實際用到的索引為聯合索引 (a, b, c)。
  • key_len = 12 表示實際用到的索引長度(字節數)為 12,這是衡量聯合索引字段生效的重要參考。
  • Extra = Using where 表示在 Server 層進行了條件過濾。
  • Extra = Using index 表示使用到了覆蓋索引。

🤔 為什么這個 where 條件明明不滿足最左前綴原則,key_len 的長度還為 12 呢?

首先說明的是,a、b、c 都是 4 字節的 int 類型,因此 索引字段數 × 字段長度 = 3 × 4 = 12 = k e y _ l e n 索引字段數 \times 字段長度 = 3 \times 4 = 12 = key\_len 索引字段數×字段長度=3×4=12=key_len 說明實際用到了 a、b、c。但這并不表明 a、b、c 索引生效!因為 type = index 表示優化器選擇了全索引掃描(遍歷整個索引),所以才呈現了 key_len = 12 的情況。

也就是說,a、b、c 沒有一個索引生效,即沒有在存儲引擎層利用索引進行條件過濾,實際的條件過濾是由 Server 層進行的。

為了進一步驗證,還可以使用 EXPLAIN ANALYZEEXPLAIN ANALYZE 是 MySQL 8.0.18 及以上版本引入的一個調試工具,用于分析 SQL 查詢的實際執行過程。它不僅顯示優化器預估的執行計劃(類似常規的 EXPLAIN),還會實際執行查詢并返回詳細的運行時統計信息(如實際耗時、處理行數等),幫助開發者精準定位性能瓶頸。

EXPLAIN analyze
SELECT *
FROM t1
WHERE a < 2 AND b > 3 AND c < 5;

image-20250326133344350

分析:

  1. Covering 表示使用到了覆蓋索引,需要查詢的所有字段都在索引搜索樹 (a, b, c) 中可以找到,無需回表查詢。
  2. index scan 表示進行了全索引掃描。
  3. Filter: ((t1.a < 2) and (t1.b > 3) and (t1.c < 5)) 表示存儲引擎層在全索引掃描后,Server 層將結果集在內存中按照 a < 2 AND b > 3 AND c < 5 進行條件過濾。

無回表 + 表數據量多

場景準備:聯合索引 (a, b, c) 已經是完整的數據記錄,可以使用覆蓋索引,表數據量多的意思是多于 1 條記錄(測試發現)。

DROP TABLE IF EXISTS t1;CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY,a INT NOT NULL,b INT NOT NULL,c INT NOT NULL,INDEX idx_a_b_c(a, b, c)
);drop procedure if exists GenerateTestData;DELIMITER //CREATE PROCEDURE GenerateTestData()
BEGINDECLARE i INT DEFAULT 0;WHILE i < 1000 DOINSERT INTO t1 (a, b, c)VALUES (FLOOR(1 + RAND() * 100),  -- 生成 1-100 的隨機整數FLOOR(1 + RAND() * 100),FLOOR(1 + RAND() * 100));SET i = i + 1;END WHILE;
END //DELIMITER ;call GenerateTestData;

接著分析此場景下的聯合索引生效情況:

EXPLAIN
SELECT *
FROM t1
WHERE a < 2 AND b > 3 AND c < 5; 

image-20250326134354221

分析:

  • type = range 表示使用索引進行范圍查找。
  • key = idx_a_b_c 表示實際用到的索引為聯合索引 (a, b, c)。
  • key_len = 4 表示實際用到的索引長度(字節數)為 4,也就是只有 a 字段索引生效
  • Extra = Using where 表示在 Server 層進行了條件過濾。
  • Extra = Using index 表示使用到了覆蓋索引。

由于進行了范圍查找,不滿足最左前綴原則,因此只有 a 字段索引生效,后續的 b、c 都未生效,并在 Server 層進行 a、b、c 的條件過濾。

🤔 Server 層為什么還會對 a 進行過濾呢,存儲引擎層不是已經過濾了 a 嗎?

這是因為存儲引擎對 Server 層是“透明”的,Server 層不假設存儲引擎的行為完全可靠,因此會重新驗證數據

為了進一步驗證,還可以使用 EXPLAIN ANALYZE

EXPLAIN analyze
SELECT *
FROM t1
WHERE a < 2 AND b > 3 AND c < 5;

image-20250326135006177

分析:

  1. Covering 表示使用到了覆蓋索引,需要查詢的所有字段都在索引搜索樹 (a, b, c) 中可以找到,無需回表查詢。
  2. range scan ... over (a < 2) 表示對 a < 2 進行了范圍掃描,僅 a 字段索引生效,b、c 未生效。
  3. Filter: ((t1.a < 2) and (t1.b > 3) and (t1.c < 5)) 表示存儲引擎層在范圍掃描后,Server 層將結果集在內存中按照 a < 2 AND b > 3 AND c < 5 進行條件過濾。

有回表

場景準備:聯合索引 (a, b, c) 不是完整的數據記錄,需要回表掃描,這里不強調表數據量大小的原因是無論數量為 0、1 或更多都會回表掃描(測試發現)。

DROP TABLE IF EXISTS t1;CREATE TABLE t1 (id INT AUTO_INCREMENT PRIMARY KEY,`name` VARCHAR(255) NOT NULL DEFAULT '',a INT NOT NULL,b INT NOT NULL,c INT NOT NULL,INDEX idx_a_b_c(a, b, c)
);DROP PROCEDURE IF EXISTS GenerateTestData;DELIMITER //CREATE PROCEDURE GenerateTestData()
BEGINDECLARE i INT DEFAULT 0;WHILE i < 1000 DOINSERT INTO t1 (a, b, c)VALUES (FLOOR(1 + RAND() * 100),  -- 生成 1-100 的隨機整數FLOOR(1 + RAND() * 100),FLOOR(1 + RAND() * 100));SET i = i + 1;END WHILE;
END //DELIMITER ;CALL GenerateTestData;

接著分析此場景下的聯合索引生效情況:

EXPLAIN
SELECT *
FROM t1
WHERE a < 2 AND b > 3 AND c < 5; 

image-20250326140358622

分析:

  • type = range 表示使用索引進行范圍查找。
  • key = idx_a_b_c 表示實際用到的索引為聯合索引 (a, b, c)。
  • key_len = 4 表示實際用到的索引長度(字節數)為 4,也就是只有 a 字段索引生效
  • Extra = Using index condition 表示在存儲引擎層使用 b、c 進行了索引下推。

由于進行了范圍查找,不滿足最左前綴原則,因此只有 a 字段索引生效,后續的 b、c 都未生效,但由于需要回表查詢,因此還可以使用 b、c 進行索引下推,且在 Server 層不會再進行條件過濾了(因為沒有提示 Extra = Using where)。

為了進一步驗證,還可以使用 EXPLAIN ANALYZE

EXPLAIN analyze
SELECT *
FROM t1
WHERE a < 2 AND b > 3 AND c < 5;

image-20250326140934661

分析:

  1. range scan ... over (a < 2) 表示對 a < 2 進行了范圍掃描,僅 a 字段索引生效,b、c 未生效。
  2. index condition: (a < 2 and b > 3 and c < 5) 表示在索引范圍掃描的基礎上,存儲引擎進一步應用索引下推,檢查索引條目是否滿足 a < 2b > 3c < 5 再進行回表掃描。

🤔 為什么生效的索引字段 a 還會作為索引下推條件呢?

雖然 a < 2 已用于范圍掃描,但 ICP 仍會重新檢查所有下推條件。也就是說,ICP 的條件列表中可能包含了已經被范圍掃描處理的條件,這是因為在索引掃描的過程中,存儲引擎可能需要再次確認這些條件,尤其是在聯合索引中,可能存在多個范圍的條目,需要逐條檢查。

總結

這里只分析了目前能想到的常見情況,其實還有很多,這是由于查詢優化器會對查詢進行優化,包括重寫查詢、決定表的讀寫順序、選擇合適的索引等,綜合考慮數據量、是否回表、回表成本、索引區分度等因素生成查詢成本最小的執行計劃。

對以上的三種情況做一個總結:

  1. 無回表 + 表數據量非常少:使用覆蓋索引進行全索引掃描,索引字段 a、b、c 都未生效(未使用索引進行條件過濾)。
  2. 無回表 + 表數據量多:使用聯合索引進行范圍查找,但只有索引字段 a 生效,Server 層使用 a、b、c 進行條件過濾(盡管存儲引擎層已經過濾了 a,但 Server 層不認為存儲引擎層行為完全可靠)。
  3. 有回表:使用聯合索引進行范圍查找,但只有索引字段 a 生效,存儲引擎層使用 a、b、c 進行索引下推(盡管大多數 ICP 場景只有 b、c 才能真正過濾掉部分數據)。

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

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

相關文章

海外營收占比近4成,泡泡瑪特全球化戰略迎收獲期

3月26日&#xff0c;泡泡瑪特國際集團發布2024全年財報。財報顯示&#xff0c;2024年泡泡瑪特實現營收130.4億元&#xff08;人民幣&#xff0c;下同&#xff09;&#xff0c;同比增長106.9%&#xff0c;經調整凈利潤34.0億元&#xff0c;同比增長185.9%。中國內地營收79.7億元…

ctf-web: 不統一的解析 + sql注入要求輸入與輸出相等 -- tpctf supersqli

# 從 django.shortcuts 模塊導入 render 函數&#xff0c;用于渲染模板 from django.shortcuts import render # 從 django.db 模塊導入 connection 對象&#xff0c;用于數據庫連接 from django.db import connection# 此模塊用于創建視圖函數 # 從 django.http 模塊導入 Http…

LLM推理加速框架有哪些

LLM推理加速框架有哪些 目錄 LLM推理加速框架有哪些1. TensorRT簡介簡單使用示例2. Triton Inference Server簡介簡單使用示例3. SGLang簡介簡單使用示例4. vLLM簡介簡單使用示例1. TensorRT 簡介 TensorRT 是 NVIDIA 推出的一個用于高性能深度學習推理的 SDK。它能夠對訓練好…

【深度學習與實戰】2.1、線性回歸模型與梯度下降法先導案例--最小二乘法(向量形式求解)

為了求解損失函數 對 的導數&#xff0c;并利用最小二乘法向量形式求解 的值&#xff0c;我們按照以下步驟進行&#xff1a; ?1. 損失函數的含義? 這是?線性回歸?的平方誤差損失函數&#xff0c;目標是最小化預測值 與真實值 之間的差距。 ?定義損失函數?&#xf…

S7-1200對V90 PN進行位置控制的三種方法

S7-1200系列PLC通過PROFINET與V90 PN伺服驅動器搭配進行位置控制,實現的方法主要有以下三種: ? 方法一、在PLC中組態位置軸工藝對象,V90使用標準報文3,通過MC_Power、MC_MoveAbsolute等PLC Open標準程序塊進行控制, 這種控制方式屬于中央控制方式(位置控制在PLC中計算,驅…

愛普生FC-135晶振5G手機的極端溫度性能守護者

在5G時代&#xff0c;智能手機不僅需要高速率與低延遲&#xff0c;更需在嚴寒、酷暑、振動等復雜環境中保持穩定運行。作為 5G 手機的核心時鐘源&#xff0c;愛普生32.768kHz晶振FC-135憑借其寬溫適應性、高精度穩定性與微型化設計&#xff0c;成為5G手機核心時鐘源的理想選擇&…

ROS--IMU數據包

IMU慣性測量單元 一&#xff1a;IMU二&#xff1a;ROS中三&#xff1a;IMU數據包三&#xff1a;總結 提示&#xff1a;以下是本篇文章正文內容&#xff0c;下面案例可供參考 一&#xff1a;IMU IMU&#xff08;Inertial Measurement Unit&#xff0c;慣性測量單元&#xff09…

數據文件誤刪除,OceanBase中如何重建受影響的節點

當不慎誤刪數據文件且當前沒有現成的可替換節點時&#xff0c;在OceanBase中&#xff0c;不必急于采取極端措施&#xff0c;可以考慮運用 server_permanent_offline_time 參數&#xff0c;來重建受影響的節點。 原理&#xff1a; server_permanent_offline_time 是 OceanBase數…

Python:匹配多個字符,如何匹配開頭

匹配字符0次或無數次(*)&#xff1a; import re resre.match([A-Z][a-z]*,Lihailu) print(res.group())#提取數據 輸出結果可以全部輸出 匹配字符至少一次()&#xff1a; import re resre.match([A-Za-z]python,apython) print(res.group())#提取數據(后邊只寫python會…

Unity-RectTransform設置UI width

不知道有沒人需要這樣的代碼&#xff0c;就是.sizeDelta //不確定是不是英文翻譯的原因&#xff0c;基本很難理解&#xff0c;sizeDeltaSize&#xff0c;//未必完全正確&#xff0c;但這么寫好像總沒錯過 //image 在一個UnityEngine.UI.Image 的數組內foreach (var image in l…

java學習——函數式編程(1)

函數式編程 Java 的函數式編程是一種以函數為核心構建邏輯的編程范式,強調不可變性、聲明式代碼和無副作用的操作。它通過Lambda表達式、函數式接口(如Function、Predicate、Consumer等)和Stream API等特性實現,將計算過程抽象為函數的組合與轉換,而非傳統的命令式步驟。…

AP CSA FRQ Q2 Past Paper 五年真題匯總 2023-2019

Author(wechat): bigshuang2020 ap csa tutor, providing 1-on-1 tutoring. 國際教育計算機老師, 擅長答疑講解&#xff0c;帶學生實踐學習。 熱愛創作&#xff0c;作品&#xff1a;ap csa原創雙語教案&#xff0c;真題梳理匯總&#xff0c; AP CSA FRQ專題沖刺, AP CSA MCQ小題…

線程池詳解:在SpringBoot中的最佳實踐

線程池詳解&#xff1a;在SpringBoot中的最佳實踐 引言 在Java并發編程中&#xff0c;線程池是一種非常重要的資源管理工具&#xff0c;它允許我們在應用程序中有效地管理和重用線程&#xff0c;從而提高性能并降低資源消耗。特別是在SpringBoot等企業級應用中&#xff0c;正…

2025年IT行業技術革命全景解析:從AI到量子計算的落地實踐

簡介 2025年&#xff0c;全球IT行業正經歷一場由AI、量子計算、物聯網等技術驅動的變革。從BOE的AI制造系統到德易科技的無人機光伏巡檢&#xff0c;從鯤鵬處理器的國產化突破到量子計算的算力革命&#xff0c;技術創新正在重塑產業格局。本文結合最新行業動態與實戰案例&…

JVM - 年輕代和老年代

通過一些問題來討論 JVM 中年輕代和老年代的內容 為什么要區分年輕代和老年代&#xff1f;哪些對像會進入老年代&#xff1f;什么時候會進行年輕代GC&#xff1f;什么時候會進行老年代GC&#xff1f; 1. 為什么要區分年輕代和老年代&#xff1f; 年輕代中的對象大部分都是短期…

【react】在react中async/await一般用來實現什么功能

目錄 基本概念 工作原理 優點 注意事項 底層原理 實際應用場景 1. 數據獲取 (API 請求) 2. 表單提交 3. 異步狀態管理 4. 異步路由切換 5. 異步數據預加載 6. 第三方 API 調用 7. 文件上傳/下載 8. 路由導航攔截 關鍵注意事項 基本概念 async 函數&#xff1a;用…

高維小樣本數據的在線流特征選擇

發布于24年國際學習和控制論雜志 文獻地址 簡要總結 《Online streaming feature selection for high-dimensional small-sample data》研究了高維小樣本數據&#xff08;HDSS&#xff09;在類別不平衡情況下的在線流式特征選擇問題&#xff0c;提出了一種名為OSFSHS的算法。…

1688.item_search_seller-搜索店鋪列表接口返回數據說明

一、接口概述 item_search_seller 是 1688 提供的一個 API 接口&#xff0c;用于搜索店鋪列表。通過該接口&#xff0c;開發者可以查詢特定店鋪的相關信息&#xff0c;包括店鋪的基本信息、商品列表等。該接口廣泛應用于電商數據采集、市場調研、店鋪分析等場景。 二、接口請…

uniapp主題切換功能,適配H5、小程序

實現方法 方法性能消耗維護成本適用場景內聯樣式較高低小程序CSS變量屬性選擇器低中H5混合方案中等低跨平臺項目 優勢特點 性能優化&#xff1a; H5端使用CSS原生變量切換小程序端使用高效樣式字符串生成切換動畫流暢 維護性提升 主題配置集中管理新增主題只需要拓展vars對象…

線程未關閉導致資源泄漏

文章目錄 資源泄漏&#xff08;線程未關閉&#xff09;問題描述錯誤實現優化原理正確實現優化原理 資源泄漏&#xff08;線程未關閉&#xff09; 問題描述 應用程序啟動時創建線程池處理任務&#xff0c;但未在應用關閉時正確關閉線程池。 現象&#xff1a; 應用重啟時&…