當mysql遇上大偏移量的limit

2021-10-02 10:29:19 字數 1109 閱讀 4775

前段時間專案中的慢sql預警郵件有類似這樣一條慢sql報警了,後來進行了優化,我們的目標是沒有慢sql,sql具體如下

select * from test  order by createtime desc limit 300000,5;
這條sql當偏移量小的時候查詢效率還是可以的,但是如果test表中的資料很大而且limit偏移量也很大的時候就會查詢效率問題。這裡來和大家一起看看為何會出現這種問題。

上面這種sql,查詢耗時太長了,肯定是過不了慢sql預警的。後來優化之後的sql如下

select * from test a inner join (select id from test order by createtime desc 

limit 300000,5) b on a.id=b.id;

兩個sql的查詢效率相差很大,為什麼會出現上面的結果?我們看一下select * from test  order by createtime desc limit 300000,5;的查詢過程:先是查詢到索引葉子節點資料,再根據葉子節點上的主鍵值去聚簇索引上查詢需要的全部字段值。類似於下面這張圖:

像上面這樣,需要查詢300005次索引節點,查詢300005次聚簇索引的資料,最後再將結果過濾掉前300000條,取出最後5條。mysql耗費了大量隨機i/o在查詢聚簇索引的資料上,而有300000次隨機i/o查詢到的資料是不會出現在結果集當中的。顯然這300000次的i/o查詢是沒有必要的。而優化之後的sql是利用子查詢的覆蓋索引,快速定位到符合條件的id,再根據這個主鍵id去查詢對應的記錄行,類似下圖

對於覆蓋索引想必大家也不陌生,我們都知道索引是高效找到行的乙個方法,但是一般資料庫也能使用索引找到乙個列的資料,因此它不必讀取整個行。畢竟索引的葉子節點儲存了它們索引的資料;當能通過讀取索引就可以得到想要的資料,那就不需要讀取行了。乙個索引包含了(或覆蓋了)滿足查詢結果的資料就叫做覆蓋索引。 

關於偏移量的理解

偏移量是個很神奇的東西,好多學科,好多方面都包含有他的知識。今天主要是想和大家分享一下自己關於偏移量的理解,以新手向為主的理解,那麼當然是言簡意賅,然後作為拋磚引玉之用吧,希望能有各路大神來補充說明。產生靈感的 主要來自於 呢?今天接觸了一些關於雙向迴圈鍊錶的東西,用老師的話講叫做 火車皮拉貨 在l...

指標偏移量的理解

今天刷題的時候碰到如下的一道題 int main array 19 2019 unsigned long offset unsigned long short array 2019 unsigned long array unsigned char array 19 cout offset 以上程式...

JS 獲取元素的偏移量

curele.parentnode document.parentnode null offsetparent 父級參照物 在同乙個平面中,最外層的元素是裡面所有元素的父級參照物 和html層級結構沒有必然的聯絡 一般來說乙個頁面中所有的父級參照物都是body body的父級參照物是null 使用p...