一篇文章講清楚MySQL的聚簇/聯合/覆蓋索引、回表、索引下推

来源:https://www.cnblogs.com/yidengjiagou/archive/2022/06/25/16410968.html
-Advertisement-
Play Games

迎面走來了你的面試官,身穿格子衫,挺著啤酒肚,髮際線嚴重後移的中年男子。 手拿泡著枸杞的保溫杯,胳膊夾著MacBook,MacBook上還貼著公司標語:“加班使我快樂”。 面試官: 看你簡歷上用過MySQL,問你幾個簡單的問題吧。什麼是聚簇索引和非聚簇索引? 這個問題難不住我啊。來之前我看一下一燈M ...


迎面走來了你的面試官,身穿格子衫,挺著啤酒肚,髮際線嚴重後移的中年男子。
手拿泡著枸杞的保溫杯,胳膊夾著MacBook,MacBook上還貼著公司標語:“加班使我快樂”。

面試官: 看你簡歷上用過MySQL,問你幾個簡單的問題吧。什麼是聚簇索引和非聚簇索引?

這個問題難不住我啊。來之前我看一下一燈MySQL八股文。

我: 舉個例子:有這麼一張用戶表

CREATE TABLE `user` (
  `id` int COMMENT '主鍵ID',
  `name` varchar(10) COMMENT '姓名',
  `age` int COMMENT '年齡',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8 COMMENT='用戶表';

用戶表中存儲了這些數據:

id nane age
1 一燈 18
2 張三 22
3 李四 21
4 王二 19
5 麻子 20

那麼在索引中,這些數據是怎麼存儲的呢?

MySQL的InnoDB引擎中索引使用的B+樹結構。

別問為什麼根節點存儲了(1,4)兩個元素,左子節點又存儲了(1,2,3)三個元素,下麵帶有三個葉子節點,葉子節點之間又用有序鏈表相連?

問就是B+樹的特性,不瞭解的可以翻一下上期的文章。

如上圖所示,葉子節點中存儲了全部元素的索引,就是聚簇索引
一般主鍵索引就是聚簇索引,如果表中沒有主鍵,MySQL也會預設建立一個隱藏主鍵做主鍵索引。

什麼是非聚簇索引?

假設我們在age(年齡)欄位上建一個普通索引,age欄位上面的索引存儲結構就是下麵這樣:

葉子節點中只存儲了當前索引欄位和主鍵ID,這樣的存儲結構就是非聚簇索引。

面試官: 那什麼是聯合索引呢?

我: 有多個欄位組成的索引就是聯合索引。

面試官: 【暈】建聯合索引有什麼好處?它跟在單個欄位上建索引有什麼區別?

我: 假設有這麼一條查詢語句。

select * from user where age = 18 and name = '張三';

如果我們在age和name欄位上分別建兩個索引,這個查詢語句只會用到其中一個索引。

但是我們在age和name欄位建一個聯合索引(age,name),它的存儲結構就變成這樣了。

如果只在age上面建索引,會先查詢age上面非聚簇索引,有三條age=18的記錄,主鍵ID分別是1、4、5,然後再用這三個ID去查詢主鍵ID的聚簇索引。

如果在age和name上面建聯合索引,會先查詢age和name上面的非聚簇索引,匹配到一條記錄,主鍵ID是1,然後再用這個ID去查詢主鍵ID的聚簇索引。

由此可以得出,聯合索引的優點:大大減少掃描行數。

面試官: 你再說一下什麼是最左匹配原則?

我: 最左匹配原則是指在建立聯合索引的時候,遵循最左優先,以最左邊的為起點任何連續的索引都能匹配上。

當我們在(age,name)上建立聯合索引的時候,where條件中只有age可以用到索引,同時有age和name也可以用到索引。但是只有name的時候是無法用到索引的。

為什麼會出現這種情況呢?

看上面的圖,就理解了,(age,name)的聯合索引,是先按照age排序,age相等的行再按照name排序。如果where條件只有一個name,當然無法用到索引。

面試官: 什麼是覆蓋索引和回表查詢?

我: 這個就更簡單了,上面已經提到這個知識點了。

當我們在age上建索引的時候,查詢SQL是這樣的時候:

select id from user where age = 18;

就會用到覆蓋索引,因為ID欄位我們使用age索引的時候已經查出來,不需要再二次回表查詢了。

但是當查詢SQL是這樣的時候:

select * from user where age = 18;

想要查詢所有欄位,就需要二次回表查詢。因為我們第一次用age索引的時候只查出來了主鍵ID,還需要再用主鍵ID回表查詢出所有欄位。

面試官: 再問一個,你知道什麼是索引下推嗎?

這麼冷門的問題,你都問的出來,真的要面試造火箭啊!

我: 索引下推(Index Condition Pushdown)是MySQL5.6引入的一個優化索引的特性。

舉例:

在(age,name)上面建聯合索引,並且查詢SQL是這樣的時候:

select * from user where age = 18 and name = '張三';

如果沒有索引下推,會先匹配出 age = 18 的三條記錄,再用ID回表查詢,篩選出 name = '張三' 的記錄。

如果使用索引下推,會先匹配出 age = 18 的三條記錄,再篩選出 name = '張三' 的一條記錄,最後再用ID回表查詢。

由此得出,索引下推的優點:減少了回表的掃描行數。

**面試官: ** 小伙子,八股文背的挺溜啊。我給你出個實戰題,看你有沒有準備。下麵這個查詢SQL該怎麼建聯合索引?

select a from table where b = 1 and c = 2;

故意刁難我?你以為實戰題就不能背八股文了嗎?

我: 剛纔在講聯合索引的時候已經說了這個知識點了,where條件有b和c的等值查詢,聯合索引就建成(b,c),由於select後面有a,我們就建立 (b,c,a) 的聯合索引,並且可以用到覆蓋索引,查詢速度更快。

面試官: 小伙子,有點東西。一會兒就給你發offer,明天就來上班,薪資double。

文章持續更新,可以微信搜一搜「 一燈架構 」第一時間閱讀更多技術乾貨。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 背景 等值查找,有數組、列表、HashMap等,已經足夠了,範圍查找,該用什麼數據結構呢?下麵介紹java中非常好用的兩個類TreeMap和ConcurrentSkipListMap。 TreeMap的實現基於紅黑樹 每一棵紅黑樹都是一顆二叉排序樹,又稱二叉查找樹(Binary Search Tre ...
  • 在大部分涉及到資料庫操作的項目裡面,事務控制、事務處理都是一個無法迴避的問題。得益於Spring框架的封裝,業務代碼中進行事務控制操作起來也很簡單,直接加個@Transactional註解即可,大大簡化了對業務代碼的侵入性。那麼對@Transactional事務註解瞭解的夠全面嗎?知道有哪些場景可能... ...
  • 寫在前面 這是我在接觸爬蟲後,寫的第二個爬蟲實例。 也是我在學習python後真正意義上寫的第二個小項目,第一個小項目就是第一個爬蟲了。 我從學習python到現在,也就三個星期不到,平時課程比較多,python是額外學習的,每天學習python的時間也就一個小時左右。 所以我目前對於python也 ...
  • 多對一關係是什麼 Django使用django.db.models.ForeignKey定義多對一關係。 ForeignKey需要一個位置參數:與該模型關聯的類 class Info(models.Model): user = models.ForeignKey(other_model,on_del ...
  • 一、什麼是智能指針 一般來講C++中對於指針指向的對象需要使用new主動分配堆空間,在使用結束後還需要主動調用delete釋放這個堆空間。為了使得自動、異常安全的對象生存期管理可行,就出現了智能指針這個概念。簡單來看智能指針是 RAII(Resource Acquisition Is Initial ...
  • 我們在做採集數據的時候,過快或者訪問頻繁,或者一訪問就給彈出驗證碼,然後就蚌珠了~ 今天就給大家來一個簡單處理驗證碼的方法 環境模塊 本文使用的是 Python和pycharm 這裡需要用到一個 ddddocr 模塊 ,這是別人開源寫好的一個東西,簡單又好用,但是精確度差一點點,但是還是非常好用的。 ...
  • mysql服務端整體架構 主要分為兩部分,server層和存儲引擎 server層包括連接器、查詢緩存、分析器、優化器、執行器等,涵蓋mysql的大多數核心服務過功能,以及所有的內置函數,所有跨存儲引擎的功能都在這一層實現,比如存儲過程,觸發器,視圖等 存儲引擎層負責數據等存儲和讀取,其架構模式是插 ...
  • tunm二進位協議在python上的實現 tunm是一種對標JSON的二進位協議, 支持JSON的所有類型的動態組合 支持的數據類型 基本支持的類型 "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "varint", "float", "s ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...