MySQL - 聚簇索引和非聚簇索引,回表查詢,索引覆蓋,索引下推,最左匹配原則

聚簇索引和非聚簇索引

聚簇索引和非聚簇索引是 InnoDB 里面的叫法

一張表它一定有聚簇索引,一張表只有一個聚簇索引在物理上也是連續存儲的

它產生的過程如下:

  1. 表中有無有主鍵索引,如果有,則使用主鍵索引作為聚簇索引;
  2. 如果沒有主鍵索引,則看表中有無唯一索引,那么使用第一個唯一索引;
  3. 如果以上兩個條件都不滿足,InnoDB 則會生成隱藏聚簇索引。

聚簇索引

聚簇索引一般是主鍵索引,

例如主鍵索引 id 對應的聚簇索引結構圖(葉子節點存儲整表數據):

?

非聚簇索引

非聚簇索引在 InnoDB 也叫做二級索引,非聚簇索引是普通列的索引(非主鍵索引)

例如普通 class_id 對應的非聚簇索引結構圖(葉子節點存儲的是聚簇索引):

?

MySQL的InnoDB索引數據結構是B+樹

聚簇索引葉子結點存儲的是行數據,而非聚簇索引葉子節點存儲的是聚簇索引,因此通過聚簇索引可以找到真正的行數據;
由于非聚簇索引的葉子結點存儲的是聚簇索引,因此使用非聚簇索引還需要進行回表查詢,所以在查詢效率方面,聚簇索引要高于非聚簇索引;
聚簇索引一般為主鍵索引,而一個表中只能有一個主鍵,因此一個表中也只能有一個聚簇索引,而非聚簇索引則沒有數量上的限制。


?什么是回表查詢?

由于非聚簇索引的葉子節點存儲的不是真正的數據,而是聚簇索引,所以在使用普通索引進行查詢操作時,會先查詢到聚簇索引,然后再去聚簇索引對應的 B+ 數去查詢真正的數據,這個過程就叫做回表查詢。


例子

下面我們創建了一個學生表,做三種查詢,來說明什么情況下是聚簇索引,什么情況下不是。

create table student (id bigint,no varchar(20) ,name varchar(20) ,address varchar(20) ,PRIMARY KEY (`branch_id`) USING BTREE,UNIQUE KEY `idx_no` (`no`) USING BTREE
)ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

第一種,直接根據主鍵查詢獲取所有字段數據,此時主鍵是聚簇索引,因為主鍵對應的索引葉子節點存儲了id=1的所有字段的值。

select * from student where id = 1

第二種,根據編號查詢編號和名稱,編號本身是一個唯一索引,但查詢的列包含了學生編號和學生名稱,當命中編號索引時,該索引的節點的數據存儲的是主鍵ID,需要根據主鍵ID重新查詢一次,所以這種查詢下no不是聚簇索引

select no,name from student where no = 'test'

第三種,我們根據編號查詢編號(有人會問知道編號了還要查詢?要,你可能需要驗證該編號在數據庫中是否存在),這種查詢命中編號索引時,直接返回編號,因為所需要的數據就是該索引,不需要回表查詢,這種場景下no是索引覆蓋?

select no from student where no = 'test'

主鍵一定是聚簇索引,MySQL的InnoDB中一定有主鍵,即便研發人員不手動設置,則會使用unique索引,沒有unique索引,則會使用數據庫內部的一個行的id來當作主鍵索引,其它普通索引需要區分SQL場景,當SQL查詢的列就是索引本身時,我們稱這種場景下該普通索引也可以叫做聚簇索引,MyisAM引擎沒有聚簇索引。


什么是索引覆蓋

????????索引覆蓋是指在一個查詢語句中,某個索引已經 "覆蓋了" 需要被查詢出來的列,此時就不需要進行回表查詢了,這就叫做索引覆蓋!!(索引覆蓋它是非聚簇索引中的一個特殊情況)

當我們寫了這樣一個 SQL,實際上它走的是輔助索引,結構如下圖:

select id from student where name = 'Bob';

  1. 輔助索引(非聚簇索引)中的查詢,一般是需要查詢兩次,第一次查詢出聚簇索引,然后根據聚簇索引回表查詢,最終拿到行數據。
  2. 但是此處我的查詢需求剛好就是聚簇索引,因此一次查詢就可以拿到需要的列,不需要進行回表,這就是索引覆蓋~

?以下四種情況都屬于索引覆蓋 >>

// 聯合索引 (name,age)
select name from student where.....
?
select age from student where.....
?
select name,age from student where.....
?
select address,name,age from student where address = '深圳';

最后一個 SQL 因為 where 條件后面可以知道 address,所以也不需要回表查詢!!


索引下推

索引下推是指在查詢非聚簇索時,拿到了葉子結點的聚簇索引,然后對聚簇索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,從而減少回表次數,這就是索引下推!!(索引下推是在 MySQL 5.6 之后才引入的,它屬于非聚簇索引中功能)

以 user 表中的聯合索引(name,age)為例:

select * from user where name='張%' and age='10';// 表中有四條數據
// 1  張三  10
// 2  張四  11
// 3  張五  12
// 4  老六  13

MySQL 5.6 之前沒有索引下推,它的執行流程如下:

① 在非聚簇索引中根據 name='張%' 查到聚簇索引中匹配的?id

② 使用匹配的 id 進行回表查詢

?此時會進行三次回表操作,而聯合索引中的 age 字段就沒用上。

MySQl 5.6 之后引入索引下推,它會根據 name='張%' 和 age 一起過濾數據:

【好處】:它的第二步操作就可以節省回表的次數

② 使用匹配的 id 進行回表查詢

?引入索引下推后,只執行了一次回表查詢,這就是索引下推的好處。


什么是最左匹配原則

  • 最左匹配原則是指索引以最左邊的為起點,任何連續的索引都能匹配上,
  • 當遇到范圍查詢 (>、<、between、like) 就會停止匹配。

比如聯合索引?index(a,b,c),以下 SQL 來理解什么是最左匹配原則:

select * from user where a=1; // 只使用索引 aselect * from user where b=2; // 不使用索引select * from user where c=3; // 不使用索引select * from user where a=1 and b=2; // 只使用索引 a,bselect * from user where a=1 and c=3; // 只是用索引 aselect * from user where b=2 and c=3; // 不使用索引select * from user where a=1 and b=2 and c=3; // 使用索引 a,b,cselect * from user where a=1 and b like '%xxx' and c=3; // 只使用索引 a,b

【疑惑一】

? ? ? ? 不是說使用了 like,就停止匹配了嗎,為什么前面的索引下推使用了 name='張%' 還能再拿 age 進行過濾呢 ?

對于 like 查詢,它的常見寫法有三種:

模糊匹配后面任意字符:like '張%'
模糊匹配前面任意字符:like '%張'
模糊匹配前后任意字符:like '%張%'
? ? ? ? 這三種情況,只有第一種情況是會走索引的,其他的都會導致索引失效,所以前面索引下推例子中的 name='張%' 是不會停止匹配的~

【疑惑二】

? ? ? ? 當我們寫出這樣的條件語句 where a=1 and c=3 and b=2 時,引擎為什么不把它調整為 a,b,c 的順序呢?

? ? ? ? MySQL 8.0 之后才涉及到這樣的調優,但是具體會不會調優,是不一定的,因為索引調優的主動權在索引的優化器里面的,而優化器這個東西,它很玄學,所以不知道它會不會進行調優。

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

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

相關文章

【Scala】Scala中的一些基本數據類型的特性 列表、元組、構造器、單例對象、伴生類、伴生對象、抽象類與特質

列表 使用List(“”,“”,“”)去聲明 sliding 和 groued表示迭代器 val iter List("Hadoop", "Spark", "Scala") sliding 2// sliding 和 groued 是有區別的while (iter.hasNext){println(iter.next())}for (elem <- iter){println(elem)}…

極速學習SSM之SpringMVC筆記

文章目錄 一、SpringMVC簡介1、什么是MVC2、什么是SpringMVC3、SpringMVC的特點 二、HelloWorld1、開發環境2、創建maven工程a>添加web模塊b>打包方式&#xff1a;warc>引入依賴 3、配置web.xmla>默認配置方式b>擴展配置方式 4、創建請求控制器5、創建springMVC…

Kafka 最佳實踐:構建可靠、高性能的分布式消息系統

Apache Kafka 是一個強大的分布式消息系統&#xff0c;被廣泛應用于實時數據流處理和事件驅動架構。為了充分發揮 Kafka 的優勢&#xff0c;需要遵循一些最佳實踐&#xff0c;確保系統在高負載下穩定運行&#xff0c;數據可靠傳遞。本文將深入探討 Kafka 的一些最佳實踐&#x…

四. 基于環視Camera的BEV感知算法-環視背景介紹

目錄 前言0. 簡述1. 環視背景介紹2. 環視思路3. 主流基于環視Camera的算法詳解總結下載鏈接參考 前言 自動駕駛之心推出的《國內首個BVE感知全棧系列學習教程》&#xff0c;鏈接。記錄下個人學習筆記&#xff0c;僅供自己參考 本次課程我們來學習下課程第四章——基于環視Camer…

基于Spring+Spring boot的SpringBoot在線電子商城管理系統

SSM畢設分享 基于SpringSpring boot的SpringBoot在線電子商城管理系統 1 項目簡介 Hi&#xff0c;各位同學好&#xff0c;這里是鄭師兄&#xff01; 今天向大家分享一個畢業設計項目作品【基于SpringSpring boot的SpringBoot在線電子商城管理系統】 師兄根據實現的難度和等級…

高云GW1NSR-4C開發板M3硬核應用

1.M3硬核IP下載&#xff1a;Embedded M3 Hard Core in GW1NS-4C - 科技 - 廣東高云半導體科技股份有限公司 (gowinsemi.com.cn) 特別說明&#xff1a;IDE必須是1.9.9及以后版本&#xff0c;1.9.8會導致編譯失敗&#xff08;1.9.8下1.1.3版本IP核可用&#xff09; 以下根據官方…

SQLMap介紹

預計更新SQL注入概述 1.1 SQL注入攻擊概述 1.2 SQL注入漏洞分類 1.3 SQL注入攻擊的危害 SQLMap介紹 2.1 SQLMap簡介 2.2 SQLMap安裝與配置 2.3 SQLMap基本用法 SQLMap進階使用 3.1 SQLMap高級用法 3.2 SQLMap配置文件詳解 3.3 SQLMap插件的使用 SQL注入漏洞檢測 4.1 SQL注入…

vue3中關于echars的使用

今天介紹一個好用的插件echars&#xff0c;一個可視化插件Apache ECharts 一、使用步驟 1、安裝 npm install echarts --save 2、導入 import * as echarts from echarts 3、正式使用 echars的使用非常的簡單&#xff0c;直接點擊官網有現成的代碼的可用 代碼示例 <t…

微服務——服務保護Sentinel

雪崩問題 在單體項目里面&#xff0c;如果某一個模塊出問題會導致整個項目都有問題。 在微服務項目里面&#xff0c;單獨一個服務出問題理論上是不會影響別的服務的。 但是如果有別的業務需要調用這一個模塊的話還是會有問題。 問題產生原因和解決思路 最初那只是一個小小…

k8s之高級調度

1. CronJob 在 k8s 中周期性運行計劃任務&#xff0c;與 linux 中的 crontab 相同 注意點&#xff1a;CronJob 執行的時間是 controller-manager 的時間&#xff0c;所以一定要確保 controller-manager 時間是準確的&#xff0c;另外 cronjobapiVersion: batch/v1 kind: CronJ…

ChatGPT 應用開發(一)ChatGPT OpenAI API 免代理調用方式(通過 Cloudflare 的 AI Gateway)

前言 開發 ChatGPT 應用&#xff0c;我覺得最前置的點就是能使用 ChatGPT API 接口。首先我自己要能成功訪問&#xff0c;這沒問題&#xff0c;會魔法就可以本地調用。 那用戶如何調用到我的應用 API 呢&#xff0c;我的理解是通過用戶能訪問到的中轉服務器向 OpenAI 發起訪問…

成都工業學院Web技術基礎(WEB)實驗四:CSS3布局應用

寫在前面 1、基于2022級計算機大類實驗指導書 2、代碼僅提供參考&#xff0c;前端變化比較大&#xff0c;按照要求&#xff0c;只能做到像&#xff0c;不能做到一模一樣 3、圖片和文字僅為示例&#xff0c;需要自行替換 4、如果代碼不滿足你的要求&#xff0c;請尋求其他的…

Echarts 環形圖配置 環形半徑(radius) 修改文本位置(label) 南丁格爾圖(roseType)

數據 const data [{ name: 華為, value: 404 },{ name: 小米, value: 800 }, { name: 紅米, value: 540 }, { name: 蘋果, value: 157 }]設置南丁格爾圖 roseType: area設置標簽位置 label: {show: true,position: center // center 中間展示 outside 外側展示 inside 內側…

C語言動態內存經典筆試題分析

C語言動態內存經典筆試題分析 文章目錄 C語言動態內存經典筆試題分析1. 題目一2. 題目二3. 題目三4. 題目四 1. 題目一 void GetMemory(char *p){p (char *)malloc(100);} void Test(void){char *str NULL;GetMemory(str);strcpy(str, "hello world");printf(str)…

Qt設置類似于qq登錄頁面

頭文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QWindow> #include <QIcon> #include <QLabel> #include <QMovie> #include <QLineEdit> #include <QPushButton>QT_BEGIN_NAMESPACE namespace Ui { class…

中國移動公網IP申請過程

一、動機 由于從事互聯網行業10年&#xff0c;一直從事移動端&#xff08;前端&#xff09;開發工作&#xff0c;未曾深入了解過后端技術&#xff0c;以至于工作10年也不算進入互聯網的門。 所以準備在自己家用設備上搭建各種場景的服務器&#xff08;云服務對個人來說成本偏…

數據分析基礎之《numpy(2)—ndarray屬性》

一、ndarray的屬性 1、屬性方法 屬性名字屬性解釋ndarray.shape數組維度的元組&#xff08;形狀&#xff09;ndarray.ndim數組維數ndarray.size數組中的元素數量ndarray.itemsize一個數組元素的長度&#xff08;字節&#xff09;ndarray.dtype數組元素的類型使用方法 數組名.…

大數據技術8:StarRocks極速全場景MPP數據庫

前言&#xff1a;StarRocks原名DorisDB&#xff0c;是新一代極速全場景MPP數據庫。StarRocks 是 Apache Doris 的 Fork 版本。StarRocks 連接的多種源。一是通過這個 CDC 或者說通過這個 ETL 的方式去灌到這個 StarRocks 里面&#xff1b;二是還可以去直接的和這些老的 kafka 或…

阿里云服務器跨域問題解決方案

首先看一下原始代碼&#xff1a; Bean public CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration new CorsConfiguration();corsConfiguration.addAllowedOrigin("http://…

spark rdd和dataframe的區別,結合底層邏輯

在 Apache Spark 中&#xff0c;RDD&#xff08;Resilient Distributed Dataset&#xff09;和 DataFrame 是處理數據的兩種不同的抽象。 RDD (Resilient Distributed Dataset) 底層實現&#xff1a; RDD 是 Spark 最初的數據抽象&#xff0c;表示一個分布式的、不可變的數據集…