覆蓋索引與聯合索引_淺析MySQL的索引覆蓋和索引下推

寫在前面

在MySQL數據庫中,索引對查詢的速度有著至關重要的影響,理解索引也是進行數據庫性能調優的起點,索引就是為了提高數據查詢的效率。今天我們來聊聊在MySQL索引優化中兩種常見的方式,索引覆蓋索引下推

索引覆蓋

要了解索引覆蓋,需要先了解幾個索引的基礎知識

B+樹索引

B+樹索引是InnoDB中的一種很常見的索引類型。關于B+樹,這里不做深入的介紹,不太清楚的小胖友可以看單獨介紹B樹、B+樹的文章。簡單來說,是因為使用B+樹存儲數據可以讓一個查詢盡量少的讀磁盤,從而減少查詢時磁盤I/O的時間。在 InnoDB 中,表都是根據主鍵順序以索引的形式存放的,這種存儲方式的表稱為索引組織表。InnoDB 使用了 B+ 樹索引模型,所以數據都是存儲在 B+ 樹中的。每一個索引在 InnoDB 里面對應一棵 B+ 樹。舉例說明,假設我們有一張表,該表主鍵為id,且有用戶名(user_name)和用戶年齡(age)兩個字段,其中age字段上有索引,所以建表語句如下圖所示:

3c499bd8729aec12b218bbb01d7e040c.png

表中有5條數據

888deb4e87cdcd76fd971fb68a47046b.png

基于上面這種表設計和表中的數據,在InnoDB中的索引結構是下面這個樣子的

eae38cd146d62429aae0355df3be16df.png

根據葉子節點的內容,索引的類型分為主鍵索引非主鍵索引
  • 主鍵索引的葉子結點存的是整條記錄,如上圖紫色部分所示

  • 非主鍵索引的葉子結點存的是主鍵的地址值,根據二級索引葉子結點中的地址可以找到主鍵索引中的這一條數據。所以非主鍵索引也被稱為二級索引,如上圖右半邊黃色部分所示

那主鍵索引、二級索引的概念和我們今天介紹的內容有什么關系呢?我們下面來具體說說回表根據剛才提供的表結構,我們嘗試來做兩次次這樣的查詢:
select *from lyb_test where id = 2select?*from?lyb_test?where?age?=?12
  • 第一條語句使用主鍵作為檢索條件,即為主鍵查詢,根據上圖所示我們知道,如果是主鍵查詢,我們只需要搜索左邊這顆主鍵索引樹即可快速查詢到id=2的這條數據

  • 第二條語句使用的是二級索引、即age作為檢索條件,這和主鍵查詢有什么區別呢?如果是二級索引查詢,則需要先搜索左側的age索引樹,得到id的值為2,再到右側的主鍵索引樹搜索一次。

像第二種查詢語句這樣,通過非主鍵索引查詢數據時,我們先通過非主鍵索引樹查找到主鍵值,然后再在主鍵索引樹搜索一次(根據rowid再次到數據塊里取數據的操作),這個過程稱為回表,也就是說非主鍵索引查詢會比主鍵查詢多搜索一棵樹

索引覆蓋

結合上面的知識儲備,我們進一步來優化一下剛才的SQL

select *from lyb_test where age = 12
當這條語句執行時,我們知道會進行兩次索引樹查詢,第一次在二級索引上查詢到主鍵索引的引用,然后到主鍵索引樹中查詢到所需要的數據,這個過程我們稱之為回表。那為什么要有回表操作呢?由于查詢的結果是所有字段,所需要的數據只有主鍵上才有,所以不得不回表。我們如果將sql改造為下面這種方式:
select id from lyb_test where age = 12

由于查詢的值是ID,而id的值已經在age索引樹上了,因此可以直接提供查詢結果,不需要回表。也就是說,當SQL語句的所有查詢字段(select列)和查詢條件字段(where子句)全都包含在一個索引中,便可以直接使用索引查詢而不需要回表。即在這個查詢里,索引age已經“覆蓋了”我們的查詢需求,故稱為索引覆蓋。

索引下推

還是基于剛才的表結構和數據,我們現在針對user_name和age建立聯合索引,索引建立之后,查詢姓名以b開頭且年齡大于等于13的用戶信息,SQL語句如下:

select * from user_table where username like 'b%' and age >= 13
語句的執行過程有兩種可能性:
  1. 根據(username,age)聯合索引查詢所有滿足名稱以"b"開頭的索引,然后回表查詢出相應的全行數據,再篩選出滿足年齡大于等于13的用戶數據。如果表中user_name以b開頭的數據有n條,則需要回表n次

  2. 根據(username,age)聯合索引查詢所有滿足名稱以"b"開頭的索引,然后直接再篩選出年齡大于等于13的索引,之后再回表查詢全行數據。經過兩次篩選之后,回表次數一定小于上述第一種情況

我們把第二種語句執行的過程稱之為索引下推在MySQL中,索引下推是默認啟用的狀態。在使用InnoDB存儲引擎的數據表中,索引下推只能用于二級索引。我們可以通過修改MySQL系統變量來控制索引下推是否開啟。設置如下:
SET?optimizer_switch?=?'index_condition_pushdown=off';//?關閉SET?optimizer_switch?=?'index_condition_pushdown=on';//?開啟

索引下推一般可用于所求查詢字段(select列)不是/不全是聯合索引的字段,查詢條件為多條件查詢且查詢條件子句(where/order by)字段全是聯合索引。假設表t有聯合索引(a,b),下面語句可以使用索引下推提高效率

select?*?from?t?where?a?>?2?and?b?>?10

上述就是索引覆蓋、回表、索引下推的相關概念和使用場景。當然針對MySQL的索引優化還有其他非常多的方式,我們可以在之后的文章中討論。本文到這里就結束啦,謝謝小伙伴們的閱讀~

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

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

相關文章

python3 輸入輸出_Python3基礎之輸入和輸出實例分析

通常來說,一個Python程序可以從鍵盤讀取輸入,也可以從文件讀取輸入;而程序的結果可以輸出到屏幕上,也可以保存到文件中便于以后使用。本文就來介紹Python中最基本的I/O函數。一、控制臺I/O1.讀取鍵盤輸入內置函數input([prompt])&…

redis 哨兵 異步_突破Java面試(23-8) - Redis哨兵主備切換的數據丟失問題-阿里云開發者社區...

1 數據丟失的兩個場景主備切換的過程,可能會導致數據丟失1.1 異步復制由于 master > slave的復制是異步的,所以可能有部分數據還沒復制到slave,master就宕機,于是這些數據就丟失了1.2 腦裂導致腦裂,也就是說&#x…

vue 斷開正在發送的請求_vue 發送請求頻繁時取消上一次請求

前言:在項目中經常有一些場景會連續發送多個請求,而異步會導致最后得到展示的結果可能不是最后一次發送請求返回的結果,且對性能也有非常大的影響。場景:列表式切換商品,有時候上一次請求的結果非常慢,而我…

Linux學習:第六章-Linux網絡配置

上一章的補充: 常見網絡端口: 2021ftp服務文件共享 22ssh服務安全遠程網絡管理 23telnet服務 25smtp:簡單郵件傳輸協議發信 110pop3:郵局協議收信 80www網頁服務 3306mysql端口 3389windows終端服務 53DNS端口 /etc/services所有系…

sequelize 增加數據庫字段_Node項目使用Sequelize操作數據庫(一)(包括模型,增,刪、改等)...

Sequelize 是一個基于 Promise 的 Node.js ORM,目前支持 Postgres、MySQL、SQLite 和 Microsoft SQL Server。它具有強大的事務支持,關聯關系、讀取和復制等功能。所謂ORM是指對象關系映射,通過使用描述對象和數據庫之間映射的元數據&#xf…

django orm插入一條_如何通過django的ORM遠程發布文章?

利用django的ORM可以方便的給數據庫插入文章但是假如我django放在阿里云,那我想在本地寫個插件,每天很方便的插入一些數據,最好是通過ORM的,因為管理起來比較方便,會涉及到多個站,可能會有200多個站&#x…

循環斐波那契數列_第五課:斐波那契數列(第一課時)

簡介:又稱黃金分割數列、因數學家列昂納多斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:1、1、2、3、5、8、13、21、34……在數學上,斐波那契數列以如下被以遞推的方法定義:F(…

命令行 藍牙_Ubuntu使用BlueZ驅動藍牙dongle

藍牙dongle即藍牙適配器,一般為USB接口,通過USB連接到PC等設備。連接dongle后,PC即可使用驅動程序控制dongle連接其它藍牙設備。本文主要介紹在Ubuntu系統中安裝BlueZ的方法及藍牙的使用。01獲取BlueZBlueZ是Linux系統的官方藍牙協議棧&#…

Java在Windows下導出xml文件到Linux服務器上

最近由于公司項目需要,學習了在Windows平臺導出xml文件到Linux服務器上的指定目錄下的方法,(注:這里的我的Linux是在本機上裝的虛擬機)現在寫下來記錄一下! 1.首先是項目截圖: 2.主要是類&…

java peek函數_Java 8 Stream Api 中的 peek 操作

1. 前言我在 Java 8 Stream API中的 map 和flatMap 中講述了Java8 Stream API中 map 操作和 flatMap 操作的區別。然后有小伙伴告訴我 peek 操作 也能實現元素的處理。但是你知道 map 和 peek 的區別嗎? map 我們在開頭文章已經講過了,你可以去詳細了解一…

iphone如何查看dns延遲_iPhone手機網速慢?1分鐘教你設置DNS,網速立馬翻一番

很多小伙伴在購機時選擇蘋果手機都是因為iOS系統的流暢度和精簡性,但iPhone在可玩性和信號方面是不如安卓手機的。大家在使用過程中一定遇到過這樣的情況,連接同一個無線網,但是蘋果的網速總是要比安卓慢,這該怎么辦呢&#xff1f…

mysql 關系_MySQL之關系

關系多對多的關系,如何通過mysql來表示站在老師的角度一個老師可以教多個學生,一個老師也可以教一個學生。站在學生的角度一個學生可以被一個老師教一個學生也可以被多個老師教結論:如果站在兩邊看都是一對多的情況,那么這個關系就…

mysql賬號密碼忘_mysql用戶名密碼忘記了解決方法

今天想用一下實驗室服務器的mysql,發現不記得用戶名密碼了。解決方法如下:1. 保證服務器處于安全的狀態,如果可以請拔掉網線...(不過我跳過了這一步,額)2. 修改/etc/my.cnf文件在[mysqld]的段中加入:skip-grant-tables…

copying mysql status_mysql慢查詢copying to tmp table

windows server,無論修改my.ini的tmp_table_size,max_heap_table_size到多少,情況都一樣。同樣的表和查詢語句,在本地運行,沒出現慢查詢。SELECTg.goods_id,g.goods_name,g.shop_price,g.goods_thumb,SUM(og.goods_num…

JDK 7,jdk1.7 安裝及配置

1.打開網頁:http://www.oracle.com 下載對應平臺的合適JDK。 2. 雙擊下載的exe,如jdk-7u7-windows-i586.exe。 3.進入安裝向導: 4.下一步,更改安裝路徑,選擇安裝所有組件。 更改為D:\jdk1.7.0_07\ 點擊確定 5.下一步,…

c mysql 編譯_MySQL編譯安裝之cmake

mysql版本5.5以上編譯安裝時需要用到軟件cmake,cmake特性是獨立于源碼編譯,編譯工作可以在另外一個目錄中而非源碼目錄中進行,mysql版本5.5以上編譯安裝時需要用到軟件cmake,cmake特性是獨立于源碼編譯,編譯工作可以在…

vb連接mysql未發現_vb連接MySQL遇到的問題解決方法

1.安裝mysql,2.安裝MyODBC-standard-3.51.07-win.msi3:vb連接語句是:Public strcnn As StringPublic sql As StringPublic conn A1.安裝mysql,2.安裝MyODBC-standard-3.51.07-win.msi3:vb連接語句是:Public strcnn As StringPublic sql As StringPublic conn As New ADODB.Conn…

mysql常用內置函數_mysql常見內置函數

在mysql中有許多內置的函數,雖然功能都能在PHP代碼中實現,但巧妙的應用mysql內置函數可以大大的簡化開發過程,提高效率。在這里我總結一下一些常用的,方便以后查看:mysql字符串函數:concat(String2 [,...])…

mysql里面有沒有map類型_MySQL學習(二) 數據類型

MySQL支持多種列類型:數值類型、日期/時間類型和字符串(字符)類型。數值類型數值類型又分為整數型與小數型整數型下面的表顯示了需要的每個整數類型的存儲和范圍創建一張表mysql> CREATE TABLE t_int (int_1 TINYINT,int_2 SMALLINT,int_3 MEDIUMINT,int_4 INT,i…

mysql alter table if_MySQL中的alter table命令的基本使用方法及提速優化

一、基本用法1. 增加列?1alter table tbl_nameadd col_name type例如, 給pet的表增加一列 weight,?1mysql>alter table petadd weightint;2. 刪除列?1alter table tbl_namedrop col_name例如, 刪除pet表中的weight這一列?1mysql>alter table petdrop weight;3. 改變…