mysql的limit分頁與between分頁

一、環境準備

mysql InnoDB有個表:

viewing_number_copy(1814483行數據)
列:id、content_id、sel_count、create_time、update_time
索引: content_id、update_time

二、觀察

要取出update_time>="2020-05-25 06:30:55"的數據,大約有20萬。

1. limit分頁

(1) 直接limit,這時實際上是依賴了默認排序,但是mysql實際上並沒有明確保證“每次查詢分頁時,總的排序不變”

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-25 06:30:55" limit 10000,1000;
在這裏插入圖片描述

(2) 先排序再limit(主鍵排序)

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-25 06:30:55" order by id limit 10000,1000;
在這裏插入圖片描述

(3) 先排序再limit(與where同索引排序)

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-25 06:30:55" order by update_time limit 10000,1000;
在這裏插入圖片描述
(1)的執行計劃與(3)相同。可見,默認排序是使用了where同索引排序。
(2)的執行計劃優於(1)(3),原因見《mysql的where、order by和limit的隱藏優化》

2. between 分頁

(1) between索引(非唯一索引)

explain select id,update_time from viewing_number_copy v where content_id between 10000 and 11000 and update_time>="2020-05-27 06:30:55";
在這裏插入圖片描述

(2) between主鍵(唯一索引)

explain select id,update_time from viewing_number_copy v where id between 10000 and 11000 and update_time>="2020-05-27 06:30:55";
在這裏插入圖片描述

三、分析

1. limit分頁有問題

要想減少大數據集的查詢對數據庫的壓力,光靠limit做分頁是不行的。不僅不會減小數據庫的壓力,還會起反作用,因爲當limit查到最後幾頁的時候,還是需要把所有符合條件的內容load到內存裏。本來沒有分頁的時候,只需要load一次所有數據就可以了,有了分頁之後,反而需要load好幾次所有數據。
所以,limit實際上只能減少數據傳輸(帶寬)的壓力,和應用服務器內存的壓力(不用一次性創建太多對象)。如果不是出於上面的兩種原因,不要用limit做分頁,而是應該從業務的角度出發,將大數據集拆分爲小數據集,分批查取
其實,limit的本意是爲了減少浪費,它最適用的場景就是取前N條數據,不用的數據先不取。顯然,對大數據集採用limit分頁的用法違背了limit的本意 (此時要使用的是全量數據,不存在“不用的數據先不取”)

2. between分頁是正解

between分頁無論翻到多少頁,掃描的條數都是固定的。但是注意要在唯一索引上進行分頁,不然每頁的大小可能會不一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章