日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

面试必会系列 - 2.1 MySQL知识点大汇总(基本架构,存储引擎,锁,事务,索引,B+树等等)

發布時間:2024/2/28 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试必会系列 - 2.1 MySQL知识点大汇总(基本架构,存储引擎,锁,事务,索引,B+树等等) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文已收錄至 Github(MD-Notes),若博客中圖片模糊或打不開,可以來我的 Github 倉庫,包含了完整圖文:https://github.com/HanquanHq/MD-Notes,涵蓋了互聯網大廠面試必問的知識點,講解透徹,長期更新中,歡迎一起學習探討 ~

更多內容,可以訪問:

面試必會系列專欄:https://blog.csdn.net/sinat_42483341/category_10300357.html
操作系統系列專欄:https://blog.csdn.net/sinat_42483341/category_10519484.html


目錄

  • MySQL
      • MySQL 基本架構
          • 連接器
          • 查詢緩存
          • 分析器
          • 優化器
          • 執行器
          • 存儲引擎
      • 零碎知識點
        • 局部性原理
          • 時間、空間局部性
          • 磁盤預讀
        • MySQL 日志有多少種?
          • Undolog 回滾日志
          • Redolog 物理日志
        • undolog 的原理?是否需要落盤?
        • MySQL有多少種鎖?
        • 使用自定義變量
        • 分區表
      • 存儲引擎
      • 事務
      • 事務的 ACID
        • 事務的實現原理
        • Atomicity 原子性:undolog
        • Consistency 一致性(數據庫的根本追求)
        • Isolation 隔離性
        • Durability 持久性:redolog + binlog
          • 思想:WAL日志(Write Ahead Log,預寫日志)
          • 采用 redo log 的好處?
        • 三種數據溢寫到磁盤的過程
        • 數據更新的流程?redo的兩階段提交
          • 數據更新的執行流程
        • MyIsam
        • Innodb
      • OLTP,OLAP
      • MySQL 索引實現原理
        • 不同存儲引擎的數據文件
        • 聚簇索引就是主鍵索引嗎?
        • Innodb 采用自適應哈希:
        • 擾動函數(Java HashMap相關的,自己看一下吧)
      • MySQL B+ 樹數據結構推導
        • 哈希表
        • 普通二叉樹
        • BST Tree(二叉排序樹)
        • AVL 樹(二叉平衡樹)
        • RBTree (紅黑樹)
        • 為什么使用 B / B+ 樹?
        • 為什么推薦使用自增的 int 類型作為主鍵?
        • 不同存儲引擎的數據結構
        • B 樹
        • B+ 樹
      • 索引分類
        • 1、按照索引的存儲來劃分:簇族索引、非簇族索引
        • 2、按照使用來分:
      • 回表 & 覆蓋索引
      • 索引下推
        • 1、沒有索引下推的情況
        • 2、有索引下推的情況
        • 3、總結


MySQL

MySQL 基本架構

連接器
  • 負責和客戶端建立連接,獲取權限,維持和管理連接

    • 用戶名密碼驗證
    • 查詢權限信息,分配對應的權限
    • 可以使用show processlist查看現有的連接
    • wait_timeout默認8小時,超時會斷開連接
  • 連接分為兩類

    • 長連接:推薦使用,但是要周期性的斷開長連接
    • 短鏈接:一次執行完畢就關閉,比較消耗資源
  • 查詢緩存
  • 當執行查詢語句的時候,會先去查看緩存中的結果,之前執行過的SQL語句會以類似于key-value的形式存在緩存中,如果能找到就返回,找不到繼續執行。
  • 不推薦使用緩存:
    • 查詢緩存失效比較頻繁,只要表更新,緩存就會清空
    • 緩存對應更新的市局命中率低
  • 分析器
  • 詞法分析:Mysql需要把輸入的字符串進行識別和翻譯
  • 語法分析:語法解析,并判斷是否符合規范
  • 優化器
  • 執行具體的SQL之前先進行優化

    • 索引優化
    • 條件順序優化
    • 關聯表順序優化
  • 不同的執行方式對效率影響很大

    • RBO:基于規則的優化
    • CBO:基于成本的優化
  • 執行器

    操作引擎,返回結果

    存儲引擎

    存儲數據,提供讀寫接口

    零碎知識點

    局部性原理

    時間、空間局部性

    數據和程序的存儲,都有聚集成群的傾向,相關關聯的數據可能被放在一起。同時,之前查詢過的數據,短時間內可能再次被查詢。

    磁盤預讀

    當內存和磁盤發生交互的時候,是以一個邏輯單元 “頁” 為單位進行交互的,“頁”是磁盤和內存交互的最小單位,一般是 4k 或 8k。讀取的時候可以以頁為單位,也可以是頁的整數倍。

    SSD 4K 對齊,能夠加快查詢效率

    MySQL 日志有多少種?

    binlog, undolog, redolog, relaylog(主從復制), errorlog, slowlog 等

    • 所有存儲引擎,都有 binlog,errorlog,relaylog,slowlog

    • Innodb 存儲引擎,有 binlog, undolog, redolog

    • MyISAM 不支持事務,沒有 undolog, redolog,只有 binlog

    Undolog 回滾日志
    Redolog 物理日志

    innodb存儲引擎的日志文件。

    • redolog是物理日志,記錄的是在某個數據頁上做了什么修改

    • 當發生數據修改的時候,innodb存儲引擎會先將記錄寫到redo_log中,并更新內存,此時更新就算是完成了,同時INNODB會在合適的時機將記錄存儲操做到磁盤中。
    • redo_log是由固定大小的,是一個循環寫的過程
    • 有了redo_log之后,innodb可以保證數據庫異常之后重啟,之前的數據記錄不會丟失,叫做crash-safe
    • binlog是邏輯日志,記錄的是這個語句的原始邏輯,比如給ID=2這一行的c字段加1;

    有且僅有兩個文件,是一個循環寫的過程。

    不知道你是否記得《孔乙己》這篇文章,酒店掌柜有一個粉板,專門記錄客人的賒賬記錄。如果賒賬的人不多,他可以將賒賬的人姓名和賬目寫在板上,但是如果賒賬的人太多,粉板總會有記不下的時候,這時候掌柜還有一個專門記錄賒賬的賬本。

    如果有人要賒賬或者還賬的時候,掌柜一般有兩種方法:

    1、一種直接將賬本翻出來,把這次賬加上或者刪除

    2、先在粉板上記下這次賬,等打烊后再把賬本翻出來核算

    在生意很忙時,掌柜應該選擇后者,第一種方法實在太麻煩了,極大的影響工作效率。

    同樣,在MySQL里也有這個問題,如果每一次更新操作都寫進磁盤,然后磁盤找到對應的那條記錄,然后再更新,整個過程的IO成本,查找成本都很高。為了解決這個問題,MySQL的設計者就用了類似酒店掌柜粉板的思路來提升工作效率。

    粉板和賬本配合的過程,其實就是MySQL里面經常說到的WAL技術,WAL技術全稱是Write-Ahead Logging.他的關鍵點就是先寫日志,再寫磁盤。

    具體來說,當有一條日志需要更新的時候。InnoDB 會先把日志寫到 redo log(粉板)中,并更新內存,這個時候更新就算完成了。同時,InnoDB 會在適當的時候將這個操作記錄到磁盤中,這個更新往往實在系統比較空閑的時候,這就像打樣以后掌柜做的事。

    如果今天賒賬的不多,掌柜可以打烊后再整理,但是某天賒賬的非常多,粉板寫滿了,又怎么辦呢?這個時候掌柜只好放下手中的事,將粉板上的賬整理到賬本上,再將粉板擦掉,為記錄新的賒賬騰出空間。

    與此類似,InnoDB 的 redo log 是固定大小的,比如可以配置為一組四個文件,每個文件的大小是1G,那么這塊粉板共有4G的空間。從頭開始寫,寫到末尾又回到開頭循環寫,如下圖所示:

    write pos 是當前記錄的位置,一邊寫一邊后移,寫到第3號文件的末尾就回到0號文件開頭。checkpoint 是當前要擦除的位置,也是往后推移并且魂環的,擦除記錄前要將記錄更新到數據文件。

    wirte 和 checkpoint 之間是粉板空著的部分,可以用來記錄新的操作。如果 write pos 追上 checkpoint,表示粉板滿了,這個時候就不能執行新的更新操作,要先停下來擦掉一些記錄,把checkpoint推進一下。

    有了redo-log,InnoDB就可以保證即使數據庫發生異常重啟,之前提交的記錄就不會丟失。這個能力成為crash-safe。

    要理解crash-safe這個概念,可以想想賒賬的例子。只要賒賬記錄記在粉板上或者寫在賬本上,之后即使掌柜忘記了,比如停業幾天,恢復生意后依然可以通過賬本和粉板上的數據明確賒賬數目。

    undolog 的原理?是否需要落盤?

    innodb通過force log at commit機制實現事務的持久性,即在事務提交的時候,必須先將該事務的所有事務日志寫入到磁盤上的 redo log file 和 undo log file 中,進行持久化。

    undo日志會記錄事務執行過程中,每次修改的數據的原始值。

    x = 5, y = 8 t1 begin:// undo日志記錄x=5x = x - 1;// undo日志記錄y=8y = y - 2;// 事務執行臨近結束,將 undolog 寫入到磁盤// 將數據寫入到磁盤 commit

    每次進行事務修改之前,把未修改之前的值存儲到 undo 日志中,提交的時候,先將 undo 寫到磁盤,再把修改后的數據寫到磁盤

    若undo寫入磁盤之前發生了異常,根本就不需要做任何操作,這時候事務是被認為執行失敗的,也不需要回滾,因為undo日志沒有寫入磁盤,數據庫被認為處于沒有執行事務的狀態。

    MySQL有多少種鎖?

    共享鎖,排它鎖,獨占鎖,間隙鎖,臨鍵鎖,自增鎖,意向鎖

    MVCC:multi version concurrency control 多版本并發控制,通過保存數據在某個時間點的快照來實現的。在同一個事務里能夠看到數據一致的視圖。

    排它鎖怎么加?query for update

    共享鎖怎么加?lock in share mode

    WAL:Write Ahead Log 溢寫日志

    使用自定義變量

    在給一個變量賦值的同時,使用這個變量

    select actor_id, @rounum:=@rownum+1 as rownum from actor limit 10;

    分區表

    創建表時使用 partition by 子句定義每個分區存放的數據,在執行查詢的時候,優化器會根據分區定義過濾那些沒有我們需要數據的分區,這樣查詢就無須掃描所有分區。

    存儲引擎

    • innodb
      • 有 redolog, undolog
      • 簇族索引
    • myisam
      • 非簇族索引
      • 不支持事務
    • memory
      • 數據在內存中,有持久化文件
      • 默認使用哈希索引

    事務

    • 數據庫事務
    • spring 聲明式事務:spring 提供了一個類,由這個類以 AOP 的方式管理,只需要@Transactional即可
    • 分布式事務

    事務的 ACID

    事務的實現原理

    事務的原子性,是通過 undo log 來實現的

    事務的持久性,是通過 redo log 來實現的

    事務的隔離性,是通過 (讀寫鎖+MVCC)來實現的

    事務的一致性,是通過原子性,持久性,隔離性來實現的!!!

    Atomicity 原子性:undolog

    innodb 默認頁 16k

    • 事務中的所有操作作為一個整體,像原子一樣不可分割(原子性),要么全部執行成功,要么全部失敗

    • 使用 undolog 邏輯日志實現回滾

      • Undo Log 是為了實現事務的原子性,在 MySQL 數據庫 InnoDB 存儲引擎中,還用 Undo Log 來實現 MVCC 多版本并發控制,記錄原來數據的歷史版本

      • 在操作任何數據之前,首先將數據備份到一個地方(這個存儲數據備份的地方稱為Undo Log)。然后進行數據的修改。如果出現了錯誤或者用戶執行了ROLLBACK語句,系統可以利用Undo Log中的備份將數據恢復到事務開始之前的狀態

        注意:undo log 是邏輯日志,可以理解為(僅理解,實際并不是這樣的):
        (區分邏輯日志、物理日志,只需要看頁是否被修改。邏輯日志 是只對當前的 sql 語句做一條記錄,而 物理日志 是對日志所在物理頁 page 做修改)

        當delete一條記錄時,undo log中會記錄一條對應的insert記錄
        當insert一條記錄時,undo log中會記錄一條對應的delete記錄
        當update一條記錄時,它記錄一條對應相反的update記錄

        如果某一次操作失敗了,就去執行這些相反的邏輯語句,將數據恢復到上一次的一致性狀態。

    Consistency 一致性(數據庫的根本追求)

    一致性分類:強一致性、弱一致性、最終一致性

    在事務的四個特點中,一致性是事務的根本追求。事務執行的結果必須使數據庫從 一個永久的一致性狀態 轉變到 另一個永久的一致性狀態。如果事務被迫中斷,不應該有一部分被寫入物理數據庫。例如,轉賬前后,兩個賬戶的總金額應該保持不變。而在某些情況下,會對事務的一致性造成破壞:

    • 事務的并發執行

    • 事務故障或系統故障

    數據庫系統通過并發控制技術日志恢復技術,來避免這種情況的發生

    • 并發控制技術保證了事務的隔離性,使數據庫的一致性狀態不會因為并發執行的操作被破壞。

    • 日志恢復技術保證了事務的原子性,使一致性狀態不會因事務或系統故障被破壞。同時使已提交的對數據庫的修改不會因系統崩潰而丟失,保證了事務的持久性。

    Isolation 隔離性

    • 使用 鎖機制 實現

    • 并發環境中,并發的事務是相互隔離的,并發執行的事務之間不能相互干擾

    • 隔離級別:假設 A,B 都開啟了事務

      • 讀未提交(未授權讀取):即使A事務未提交,B事務也能看到A的修改
      • 讀已提交(授權讀取):A事務提交后,B事務中才能看到A的修改
      • 可重復讀:無論A怎么修改,事務B在事務期間都不會看到A的修改
      • 串行化:所有事物只能一個接一個處理,不能并發執行

      (要能夠模擬臟讀、幻讀、不可重復讀的情況)

    Durability 持久性:redolog + binlog

    我們知道,寫數據的時候,數據會先存在用戶空間內存中,然后由操作系統內核調用 fsync,才真正寫入到磁盤。如果此時突然宕機,內存中的數據就會丟失。怎么解決這個問題?

    事務提交前直接把數據寫入磁盤就行啊。這么做有什么問題?只修改一個頁面里的一個字節,就要將整個頁面刷入磁盤,太浪費資源了。畢竟一個頁面16kb大小,你只改其中一點點東西,就要將16kb的內容刷入磁盤,聽著也不合理。畢竟一個事務里的SQL可能牽涉到多個數據頁的修改,而這些數據頁可能不是相鄰的,也就是屬于隨機IO。顯然操作隨機IO,速度會比較慢。

    思想:WAL日志(Write Ahead Log,預寫日志)

    采用 redo log 解決上面的問題。當做數據修改的時候,不僅在內存中操作,還會在redo log中記錄這次操作。當事務提交的時候,將redo log日志進行刷盤持久化即可(redo log一部分在內存中,一部分在磁盤上),不需要將數據持久化。當數據庫宕機重啟的時候,雖然數據沒有持久化,但是可以根據 redo log 中的內容,將數據恢復到數據庫中,再根據 undo log 和 binlog 內容決定回滾數據還是提交數據。

    采用 redo log 的好處?

    redo log 進行刷盤比對數據頁刷盤效率高

    • redo log體積小,畢竟只記錄了哪一頁修改了啥,因此體積小,刷盤快。
    • redo log是一直往末尾進行追加,屬于順序IO。效率顯然比隨機IO來的快。

    • 事務一旦提交,數據必須永久保存。即使宕機,重啟后也能恢復到事務成功結束時的狀態
    • 使用 redolog 兩階段提交實現。事務提交前,需要將 redolog 持久化。系統崩潰時,雖然數據沒有持久化,但是可以根據 redolog 的內容,將數據恢復到最新的狀態。
    • redolog 大小是固定的,相當于一個增量存儲,redolog 滿了之后,會進行持久化的同步歸檔。然后將redolog清空。

    三種數據溢寫到磁盤的過程

  • 效率最高。只要 redolog 寫成功了,斷電也沒關系
  • 最安全
  • 與 1 相比更安全,如果 MySQL 進程掛了,數據不會丟失,操作系統會繼續處理寫數據
  • 數據更新的流程?redo的兩階段提交

    事實分析先寫redolog后寫binlog和先寫binlog后寫redolog都會有數據不一致的風險。
    因此,采用兩階段提交,具體流程如下:

    數據更新的執行流程

  • 執行器先從存儲引擎找到數據,如果在內存中直接返回,不在內存中查詢返回

  • 執行器拿到數據后會先修改數據,然后調用引擎接口重新吸入數據

  • 引擎將數據更新到內存,同時寫數據到redo中,此時處于prepare階段,并通知執行器執行完成

  • 執行器生成這個操作的binlog

  • 執行器調用引擎的事務提交接口,引擎把剛寫完的redo改為commit狀態

  • 更新完成

  • 使用 兩階段提交的優勢 是:可以保證 binlog 和 redolog 的數據一致(先寫 redolog 或者先寫 binlog 都無法保證突然宕機時的數據一致性)。如果數據庫發生了意外情況,宕機、斷點、重啟等等,可以保證使用 BinLog 恢復數據和當時數據狀態一致。具體情況下的策略如下:

    • binlog有記錄,redolog狀態commit:正常完成的事務,不需要恢復
    • binlog有記錄,redolog狀態prepare:在binlog寫完提交事務之前的crash,恢復操作:提交事務
    • binlog無記錄,redolog狀態prepare:在binlog寫完之前的crash,恢復操作:回滾事務
    • binlog無記錄,redolog無記錄:在redolog寫之前crash,恢復操作:回滾事務

    • 共享鎖
    • 排它鎖
    • 獨占鎖
    • 臨鍵鎖
    • 間隙鎖
    • 自增鎖
    • 意向鎖

    MyIsam

    只能鎖表

    • 共享讀鎖
    • 獨占寫鎖

    Innodb

    支持表鎖,行鎖。實質上鎖的是索引,如果沒有索引的話,退化成為表鎖。

    • 共享鎖(s),又稱讀鎖
    • 排它鎖(x),又稱寫鎖

    OLTP,OLAP

    OLTP:聯機事務處理,在盡可能短的時間內返回對應的結果值。例如我們常用的關系型數據庫。

    OLAP:聯機分析處理,Hive,主要是對歷史數據的分析,用于做出決策;常用于數據倉庫。不支持范圍查詢,插入新數據要重排?

    區別在于時效性,在很短的時間內返回結果。

    MySQL 索引實現原理

    索引是和存儲引擎相關聯的。所謂存儲引擎,指的是數據在磁盤上的不同組織形式。

    Memory 存儲引擎使用 Hash 索引。

    不同存儲引擎的數據文件

    I nnodb:包括 frm(表結構),ibd(索引+數據放在一起,聚簇索引) 文件

    MyISAM:包括 frm,myd,myi 文件,非聚簇索引

    聚簇索引就是主鍵索引嗎?

    不一定是。

    • 如果你建表時不指定主鍵,innodb會選擇 唯一鍵 創建索引。
    • 如果沒有唯一鍵的話,會生成一個 6 字節的 row_id 作為主鍵。

    Innodb 采用自適應哈希:

    當給 colA 建 立B+tree 索引的時候,這棵 B+ tree 會有個三四層,通過 colA = ‘xxx’ 會在樹里查詢 3、4 次才能查到,所以這里如果開啟了自適應索引,就利用 buffer pool 來給 colA 建立一個哈希索引,這樣就只用在哈希索引里查 1 次,不用在 B+ tree 里查詢 3、4 次,加快了速度。

    擾動函數(Java HashMap相關的,自己看一下吧)

    static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }

    目的是為了減少hash沖突。

    MySQL B+ 樹數據結構推導

    哈希表

    哈希算法應該你可能多的案列,讓數據分布均勻,使用擾動函數,減少hash沖突;對內存占用比較高;檢索時無法進行范圍查詢,如果范圍查詢,必須逐個對比,相當耗費時間。

    MySQL用到了哈希表嗎?Memory 存儲引擎使用的索引數據結構就是哈希表;Innodb使用自適應哈希。

    普通二叉樹

    查詢效率太低,需要遍歷整個樹

    BST Tree(二叉排序樹)

    有序,左子樹<根節點<右子樹,遞增插入會退化成鏈表,是因為樹不夠平衡

    AVL 樹(二叉平衡樹)

    最短子樹和最長子樹高度之差不能超過1,是嚴格意義上的平衡樹,在插入數據的時候要進行旋轉操作來保證平衡,會損失部分插入性能,從而帶來查詢性能的提升

    RBTree (紅黑樹)

    非嚴格的平衡樹,最長路徑不超過最短路徑的兩倍。近似取得了插入和查詢性能的平衡。

    為什么使用 B / B+ 樹?

    以上的“二叉”樹都會越來越深,每一個節點中只能存一個元素。如果數據節點很多,查找的時候,需要進行多次 IO 交互。應該盡量在 4k 中存儲盡可能多的數據節點。

    B / B+ 樹的每一個節點中可以有多個元素,采用有序、多分支的方式,解決二叉樹的這些弊端。

    為什么推薦使用自增的 int 類型作為主鍵?

    int 類型 相比 varchar,占用的索引空間比較小

    自增可以直接追加在最后面,減少樹的頁分裂、合并帶來的維護成本

    不同存儲引擎的數據結構

    Innodb 默認使用 B-tree,根據官網文檔,Memory tables 也支持哈希索引。

    Hash劣勢:rehash,哈希沖突問題。不好的hash算法導致散列不均勻,浪費磁盤空間。

    jdk 1.8 的哈希函數算法使用了擾動函數,也是為了讓散列更均勻

    索引MyISAM引擎InnoDB引擎Memory引擎
    B-Tree索引支持支持支持
    HASH索引不支持不支持支持
    R-Tree索引支持不支持不支持
    Full-text索引支持不支持不支持

    B 樹

    實例圖說明:

    B+ 樹

    每個節點可以包含多個元素,有 n 棵子樹的節點中含有 n 個關鍵字。每個關鍵字不保存數據,只用來索引。

    非葉子結點只存儲 key,不存儲數據。所有 數據都放在葉子結點 中存儲。是為文件系統而生的。

    B+Tree是在B Tree的基礎之上做的一種優化,變化如下:

  • B+Tree每個節點可以包含更多的節點,這么做的原因有兩個,一個原因是為了降低樹的高度,第二個原因是將數據范圍變為多個區間,區間越多,數據檢索越快
  • 非葉子節點存儲key,葉子節點存儲key和數據
  • 葉子節點兩兩指針相互連接(符合磁盤預讀性),順序查詢性能更高
  • 索引分類

    1、按照索引的存儲來劃分:簇族索引、非簇族索引

    聚簇索引:innodb 數據和索引放在一起。如果不設主鍵,innodb 會選擇一個唯一鍵,如果沒有唯一鍵,innodb會生成一個 6 字節的 rowid 存儲,對用戶是不可見的。因此,聚簇索引不一定是主鍵索引。

    非聚簇索引:數據和索引不放在一起,myisam

    2、按照使用來分:

    主鍵索引:主鍵所關聯的數據

    唯一索引:mysql 默認會給唯一鍵添加索引

    普通索引:用來加速數據訪問速度而建立的索引。多建立在經常出現在查詢條件的字段和經常用于排序的字段。普通索引是非聚簇索引,葉子存放的是對應主鍵id值。

    另外,如果主鍵是創建表之后才添加的,新建立的主鍵的索引使用的不是主鍵索引,而是在葉子上去關聯原來默認的 rowid。因此,innodb 的主鍵索引也不一定是聚簇索引。

    回表 & 覆蓋索引

    回表:通過普通索引去樹中查找,會 返回主鍵值,再 **根據主鍵 **去索引樹查找數據。

    select id, age from test where name = '張三';

    覆蓋索引:執行計劃能看到 using index。通過檢索索引就可以讀取想要的數據,那就不需要再到數據表中讀取行了。也就是不需要回表。

    select id, name from test where name = '張三';

    索引下推

    假設有這么個需求,查詢表中“名字第一個字是張,性別男,年齡為10歲的所有記錄”。那么,查詢語句是這么寫的:

    mysq> select * from tuser where name like '張%' and age=10 and ismale=1;

    根據前面說的“最左前綴原則”,該語句在搜索索引樹的時候,只能匹配到名字第一個字是‘張’的記錄(即記錄ID3),接下來是怎么處理的呢?當然就是從ID3開始,逐個回表,到主鍵索引上找出相應的記錄,再比對age和ismale這兩個字段的值是否符合。

    但是!MySQL 5.6引入了索引下推優化,可以在索引遍歷過程中,對索引中包含的字段先做判斷,過濾掉不符合條件的記錄,減少回表字數。

    1、沒有索引下推的情況

    圖 1 中,在 (name,age) 索引里面,我特意去掉了 age 的值,因為 這個過程 InnoDB 并不會去看 age 的值,只是按順序把“name 第一個字是’張’”的記錄一條條取出來回表。因此,需要回表 4 次。

    2、有索引下推的情況

    圖 2 跟圖 1 的區別是,InnoDB 在 (name,age) 索引內部就判斷了 age 是否等于 10,對于不等于 10 的記錄,直接判斷并跳過。在我們的這個例子中,只需要對 ID4、ID5 這兩條記錄回表取數據判斷,就只需要回表 2 次。

    3、總結

    如果沒有索引下推優化(或稱ICP優化),當進行索引查詢時,首先根據索引來查找記錄,然后再根據where條件來過濾記錄;在支持ICP優化后,MySQL會在取出索引的同時,判斷是否可以進行where條件過濾再進行索引查詢,也就是說提前執行where的部分過濾操作,在某些場景下,可以大大減少回表次數,從而提升整體性能。

    總結

    以上是生活随笔為你收集整理的面试必会系列 - 2.1 MySQL知识点大汇总(基本架构,存储引擎,锁,事务,索引,B+树等等)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。