1. 程式人生 > >mysql優化:覆蓋索引(延遲關聯)

mysql優化:覆蓋索引(延遲關聯)

前言

上週新系統改版上線,上線第二天就出現了較多的線上慢sql查詢,緊接著dba 給出了定位及解決方案,這裡較多的是使用延遲關聯去優化。
而我對於這個延遲關聯也是第一次聽說(o(╥﹏╥)o),所以今天一定要學習併產出一篇學習筆記。(^▽^)

回表

我們都知道InnoDB採用的B+ tree來實現索引的,索引又分為主鍵索引(聚簇索引)和普通索引(二級索引)。
那麼我們就來看下基於主鍵索引和普通索引的查詢有什麼區別?

  • 如果語句是select * from T where ID=500,即主鍵查詢方式,則只需要搜尋ID這棵B+樹;
  • 如果語句是select * from T where k=5,即普通索引查詢方式,則需要先搜尋k索引樹,得到ID的值為500,再到ID索引樹搜尋一次。這個過程稱為回表。

舉個栗子:

   

可以看出我們有一個普通索引k,那麼兩顆B+樹的示意圖如下:


(注:圖來自極客時間專欄)

當我們查詢 select * from T where k=5 其實會先到k那個索引樹上查詢k = 5,然後找到對應的id為500,最後回表到主鍵索引的索引樹找返回所需資料。
如果我們查詢select id from T where k=5 則不需要回表就直接返回。
也就是說,基於非主鍵索引的查詢需要多掃描一棵索引樹。因此,我們在應用中應該儘量使用主鍵查詢。

覆蓋索引

  • 解釋一: 就是select的資料列只用從索引中就能夠取得,不必從資料表中讀取,換句話說查詢列要被所使用的索引覆蓋。
  • 解釋二: 索引是高效找到行的一個方法,當能通過檢索索引就可以讀取想要的資料,那就不需要再到資料表中讀取行了。如果一個索引包含了(或覆蓋了)滿足查詢語句中欄位與條件的資料就叫做覆蓋索引。
  • 解釋三:是非聚集組合索引的一種形式,它包括在查詢裡的Select、Join和Where子句用到的所有列(即建立索引的欄位正好是覆蓋查詢語句[select子句]與查詢條件[Where子句]中所涉及的欄位,也即,索引包含了查詢正在查詢的所有資料)。
  • 不是所有型別的索引都可以成為覆蓋索引。覆蓋索引必須要儲存索引的列,而雜湊索引、空間索引和全文索引等都不儲存索引列的值,所以MySQL只能使用B-Tree索引做覆蓋索引
  • 當發起一個被索引覆蓋的查詢(也叫作索引覆蓋查詢)時,在EXPLAIN的Extra列可以看到“Using index”的資訊

概念如上,這裡我們還是用例子來說明:

 
 


(注:圖來自極客時間專欄)
現在,我們一起來看看這條SQL查詢語句的執行流程:

  1. 在k索引樹上找到k=3的記錄,取得 ID = 300;
  2. 再到ID索引樹查到ID=300對應的R3;
  3. 在k索引樹取下一個值k=5,取得ID=500;
  4. 再回到ID索引樹查到ID=500對應的R4;
  5. 在k索引樹取下一個值k=6,不滿足條件,迴圈結束。

在這個過程中,回到主鍵索引樹搜尋的過程,我們稱為回表。可以看到,這個查詢過程讀了k索引樹的3條記錄(步驟1、3和5),回表了兩次(步驟2和4)。
在這個例子中,由於查詢結果所需要的資料只在主鍵索引上有,所以不得不回表。那麼,有沒有可能經過索引優化,避免回表過程呢?

如果執行的語句是select ID from T where k between 3 and 5,這時只需要查ID的值,而ID的值已經在k索引樹上了,因此可以直接提供查詢結果,不需要回表。也就是說,在這個查詢裡面,索引k已經“覆蓋了”我們的查詢需求,我們稱為覆蓋索引。
由於覆蓋索引可以減少樹的搜尋次數,顯著提升查詢效能,所以使用覆蓋索引是一個常用的效能優化手段。
需要注意的是,在引擎內部使用覆蓋索引在索引k上其實讀了三個記錄,R3~R5(對應的索引k上的記錄項),但是對於MySQL的Server層來說,它就是找引擎拿到了兩條記錄,因此MySQL認為掃描行數是2。

延遲關聯

上面介紹了那麼多 其實是在為延遲關聯做鋪墊,這裡直接續上我們本次慢查詢的sql:

我們都知道在做分頁時會用到Limit關鍵字去篩選所需資料,limit接受1個或者2個引數,接受兩個引數時第一個引數表示偏移量,即從哪一行開始取資料,第二個引數表示要取的行數。 如果只有一個引數,相當於偏移量為0。
當偏移量很大時,如limit 100000,10 取第100001-100010條記錄,mysql會取出100010條記錄然後將前100000條記錄丟棄,這無疑是一種巨大的效能浪費。

當有這種寫法時,我們可以採用延遲關聯來進行優化,重點關注:** SELECT id FROM qa_question WHERE expert_id = 69 AND STATUS = 30 ORDER BY over_time DESC LIMIT 0, 10**, 這裡其實利用了索引覆蓋,where條件後的expert_id 是有新增索引的,這裡查詢id 可以避免回表,大大提升效率。

結語

工作中會遇到各種各樣的問題,對於一個研發來說最重要的是能夠從這些問題中學到什麼。好久沒有寫部落格了,究其原因還是自己變得懶惰了。
接下來還有很多東西需要學習,也是平時工作中所用到的,列舉一下如:設計模式、dubbo、rediss等等,加油吧少年。
最後以《高效能Mysql》中的一段話結束:

相關推薦

mysql優化覆蓋索引延遲關聯

前言 上週新系統改版上線,上線第二天就出現了較多的線上慢sql查詢,緊接著dba 給出了定位及解決方案,這裡較多的是使用延遲關聯去優化。 而我對於這個延遲關聯也是第一次聽說(o(╥﹏╥)o),所以今天一定要學習併產出一篇學習筆記。(^▽^) 回表 我們都知道InnoDB採用的B+ tree來實現索引

優化limit分頁延遲關聯

limit'分頁有一個問題就是當偏移量較大時查詢遍歷的資料越多,效率會逐漸降低,例如limit 1000,10這樣的查詢這時MYSQL需要查詢出1020條記錄然後只返回最後20條,前面的1000條記錄都會被拋棄,代價較高。如果每個分頁被訪問的資料頻率都相同要優化這種查詢要麼

多執行緒下單例模式懶載入延遲載入和即時載入

前言 在開發中,如果某個例項的建立需要消耗很多系統資源,那麼我們通常會使用惰性載入機制,也就是說只有當使用到這個例項的時候才會建立這個例項,這個好處在單例模式中得到了廣泛應用。這個機制在single-threaded環境下的實現非常簡單,然而在multi-t

PostgreSQL 11 新特性之覆蓋索引Covering Index

文章目錄 通常來說,索引可以用於提高查詢的速度。通過索引,可以快速訪問表中的指定資料,避免了表上的掃描。 有時候,索引不僅僅能夠用於定位表中的資料。某些查詢可能只需要訪問索引的資料,就能夠獲取所需要的結果,而不需要再次訪問表中的資料。這種訪問資料的方法叫做 In

MySQL優化案例---半連線semi join優化方式 導致的查詢效能低下

MySQL V5.6.x/5.7.x SQL查詢效能問題 一 簡單建立一表,並使用儲存過程插入一部分資料CREATE TABLE users (  user_id int(11) unsigned NOT NULL,  user_name varchar(64) DEFAULT NULL,  PRIMARY

Mysql性能優化覆蓋索引

查找 cnblogs 都是 記錄 性能優化 nod 如果 libary 使用 因為我們大多數情況下使用的都是Innodb,所以這篇博客主要依據Innodb來講 b+樹(圖片來自網絡)

MySQL SQL優化覆蓋索引

內容概要 利用主索引提升SQL的查詢效率是我們經常使用的一個技巧,但是有些時候MySQL給出的執行計劃卻完全出乎我們的意料,我們預想MySQL會通過索引掃描完成查詢,但是MySQL給出的執行計劃卻是通過全表掃描完成查詢的,其中的某些場景我們可以利用覆蓋索引進行優化。

MySQL】效能優化覆蓋索引

mysql中的一種十分高效有用的索引---覆蓋索引。 覆蓋索引用通俗的話講就是在select的時候只用去讀取索引而取得資料,無需進行二次select相關表。這樣的索引的葉子節點上面也包含了他們索引的資料。 select * from table_name; select id,name from table_

SQL優化基本概念索引調優、統計資訊、查詢調整、資源調控

 1、索引碎片 /*======================================================= 注意:所有的引數都是以當前資料庫來計算的,所以必須指定完全限定。 模式影響如何收集碎片資料: LIMITED:掃描堆所有的頁,對於索引,

SQL優化基礎使用索引一個小例子

       一年多沒寫,偶爾會有衝動寫幾句,每次都欲寫又止,有時候寫出來就是個記錄,沒有其他想法,能對別人有用也算額外的功勞 按照本文操作和體會,會對sql優化有個基本最簡單的瞭解,其他深入還需要更多資料和實踐的學習: 1. 建表: create table site_user ( id

MySQL全面瓦解24構建高效能索引策略篇

學習如果構建高效能的索引之前,我們先來了解下之前的知識,以下兩篇是基礎原理,瞭解之後,對面後續索引構建的原則和優化方法會有更清晰的理解: MySQL全面瓦解22:索引的介紹和原理分析 MySQL全面瓦解23:MySQL索引實現和使用 我們編寫索引的目的是什麼?就是使我們的sql語句執行得更加高效,更快的獲取或

MySQL 8.0實驗室---MySQL中的倒敘索引Descending Indexes

mysql 重新 .cn 創建表 https 正序 tro 一個 刪除 譯者註:MySQL 8.0之前,不管是否指定索引建的排序方式,都會忽略創建索引時候指定的排序方式(語法上不會報錯),最終都會創建為ASC方式的索引,在執行查詢的時候,只存在forwarded(正向

優化演算法牛頓法Newton法

學習深度學習時遇到二階優化演算法牛頓法,查閱了相關書籍進行記錄。 :函式的梯度向量 :函式的Hessian矩陣,其第i行第j列的元素為. 假設是二階連續可微函式,。最速下降法因為迭代路線呈鋸齒形,固收斂速度慢,僅是線性的。最速下降法本質使用線性函式去近似目標函式。要得到快速的演算法,

ExtJs效能優化tab的資料延遲載入

今天碰到一個問題,當點選某一行資料,顯示詳情時,由於詳情又有四個子tab,每個子tab都是一個表格,有各種各樣的請求,當點選該行資料顯示詳情時,所有的資料同時載入,導致頁面卡頓,此時做ExtjS的效能優化是很重要的。通過研究,瞭解了一下ExtJs的效能優化和前端的效

Mysql優化選擇最佳索引使用方法

索引的目的在於提高查詢效率,其功能可類比字典,通過該索引可以查詢到我們想要查詢的資訊,因此,選擇建立好的索引十分重要,以下是為Mysql優化選擇最佳索引的方法步驟: 1. 首先列出查詢中所有使用的表,併為查詢中的每個子查詢建立一個獨立的列表。如果有一個包含 2 個 SELE

sql主鍵primary key和唯一索引unique index區別

主鍵一定是唯一性索引,唯一性索引並不一定就是主鍵。  所謂主鍵就是能夠唯一標識表中某一行的屬性或屬性組,一個表只能有一個主鍵,但可以有多個候選索引。因為主鍵可以唯一標識某一行記錄,所以可以確保執行資料更新、刪除的時候不會出現張冠李戴的錯誤。主鍵除了上述作用外,常常與外來鍵構成參照完整性約束

Mysql之DQL複雜查詢連線查詢

1、內連線查詢:inner join 表名2 別名2 on 別名2.有關係欄位名=別名1.有關係欄位名 有條件就用where 例子1:把參加考試的同學資訊查出來 select s.StudentName,r.StudentResult from st

MySQL資料庫優化——MySQL悲觀鎖&&樂觀鎖併發控制

一、悲觀鎖     1、排它鎖,當事務在操作資料時把這部分資料進行鎖定,直到操作完畢後再解鎖,其他事務操作才可操作該部分資料。這將防止其他程序讀取或修改表中的資料。     2、實現:大多數情況下依靠資料庫的鎖機制實現      一般使用 select ...for upd

效能優化監控索引的使用情況

黃瑋(Fuyuncat),資深 Oracle DBA,從事 Oracle 資料庫管理、維護與開發工作十餘年,有豐富的大型資料庫設計、開發與維護方面的經驗,部落格www.HelloDBA.com, 編輯手記:索引的合理使用能夠提高SQL的執行效率,但索引並不是萬能的,也不是所有的索引都會被Oracl

百萬資料排序優化的選擇排序堆排序

本博文介紹首先介紹直接選擇排序,然後針對直接選擇排序的缺點改進的“堆排序”,堆排序非常適合:陣列規模非常大(數百萬或更多) + 嚴格要求輔助空間的場景。 直接選擇排序 (一)概念及實現 直接選擇排序的原理:將整個陣列視為虛擬的有序區和無序區,重複的遍歷陣列,每次遍歷從無序區中選出一個最小