偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

這真的不是八股!經典 MySQL 大數據量查詢分頁問題

數據庫 MySQL
從業(yè)務角度來說,可以認為超過這個最大值用戶已經不是在分頁了,而是在刷數據,如果確實是要找某條數據,那么正常理解應該是輸入合適的條件來適當縮小范圍,而不是一頁一頁地分頁。

查詢分頁一般要最少要執(zhí)行兩條 SQL 語句:

SELECT COUNT(*) FROM tablename WHERE columnName = 'xx'
SELECT * FROM tablename WHERE columnName = 'xx' limit 0,100

正常情況下沒有問題,但是當數據量非常大的時候,首先 count(*) 會非常慢這是肯定的,其次分頁越多,limit 的效率就會越低。

比如 limit 200000, 10,這個等同于數據庫要掃描出 200010 條數據,然后再丟棄前面的 200000 條數據,返回剩下 10 條數據給用戶,這種取法很明顯越往后速度越慢,妥妥的慢 SQL。

《高性能 MySQL》中對這個問題有過說明:

分頁操作通常會使用 limit 加上偏移量的辦法實現(xiàn),同時再加上合適的 order by 子句。但這會出現(xiàn)一個常見問題:當偏移量非常大的時候,它會導致 MySQL 掃描大量不需要的行然后再拋棄掉。

數據模擬

我們創(chuàng)建兩張表(部門表和員工表),并模擬插入 500w 條員工數據

圖片

測試下分頁查詢員工的 SQL 執(zhí)行速度,先來看偏移量比較小的情況:

SELECT a.empno,a.empname,a.job,b.depno,b.depname
from emp a 
left join dep b 
on a.depno = b.depno 
order by a.id 
desc limit 100,25;

受影響的行: 0
時間: 0.001s

再來看下偏移量非常大的情況:

SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a 
left join dep b 
on a.depno = b.depno 
order by a.id 
desc limit 4800000,25;

受影響的行: 0
時間: 12.275s

可以很明顯的看出,偏移量很小的時候,查詢速度還是非??斓模斊屏可系桨偃f量級,這個執(zhí)行時間已經無法忍受了,一條查詢語句跑十幾秒這不直接給數據庫干阻塞了?

優(yōu)化方案

使用覆蓋索引 + 子查詢

偏移量之前的數據是沒有價值的,所以我們可以先在聚集索引中根據偏移量找到開始位置的 id 值,再根據這個 id 值去非聚集索引上查詢所需要的行數據,這樣就避免了大量的無用的回表查詢。

總結來說就是:利用子查詢獲取偏移 n 條的位置 id,基于這個位置再往后取

SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a 
left join dep b 
on a.depno = b.depno
where 
 a.id >= (select id from emp order by id limit 4800000,1)
order by a.id 
limit 25;

受影響的行: 0
時間: 1.541s

可以看見,執(zhí)行效率有顯著提升

記錄上次查找位置

這個應該是比較常見的解決手段了,就是記住上次查找結果的主鍵位置,從而避免使用偏移量。

比如存儲了上次分頁的最后一條數據 id 是 4800000,SQL 就可以直接跳過4800000,從 4800001 開始掃描表

SELECT a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a 
left join dep b 
on a.depno = b.depno
where 
 a.id > 4800000
order by a.id 
limit 25;

受影響的行: 0
時間: 0.000s

這個效率是最好的,無論怎么分頁,耗時基本都是一致的,因為他執(zhí)行完條件之后,都只掃描了 25 條數據。

但這種方案只適合順序分頁(比如 Feeds 流場景),這樣才能記住前一個分頁的最后 id。如果用戶跳著分頁,比如剛剛刷完第 25 頁,馬上跳到 35 頁,使用這種方案的話,數據顯示的其實是 26 頁的數據,而不是 35 頁的。

降級

這種方案屬于兜底策略:為 limit 和 offset 設置一個最大值,超過這個最大值,分頁查詢接口就直接返回空數據或者返回錯誤碼

從業(yè)務角度來說,可以認為超過這個最大值用戶已經不是在分頁了,而是在刷數據,如果確實是要找某條數據,那么正常理解應該是輸入合適的條件來適當縮小范圍,而不是一頁一頁地分頁。

責任編輯:武曉燕 來源: 飛天小牛肉
相關推薦

2018-09-06 16:46:33

數據庫MySQL分頁查詢

2021-10-26 14:40:03

MySQL SQL 語句數據庫

2023-11-29 17:28:07

2021-11-04 14:32:17

Spring 面試作用域

2025-10-15 03:00:00

2021-10-21 14:43:23

Java 語言 Java 基礎

2018-05-15 08:44:44

TensorFlowKeras內存

2021-07-26 14:59:23

面試Redis內存數據庫

2021-09-07 14:46:42

面試網絡HTTP 協(xié)議

2022-05-06 22:13:56

JVM垃圾收集算法

2011-08-16 09:21:30

MySQL大數據量快速語句優(yōu)化

2011-04-18 11:13:41

bcp數據導入導出

2021-01-07 07:46:34

MyBatis 數據量JDBC

2021-10-26 17:05:55

Redis字符串復雜度

2023-11-28 18:09:49

Java多態(tài)

2022-09-03 11:36:11

Python文件網絡

2015-03-09 10:40:44

MySQL大量數據插入

2021-08-01 22:59:43

Object八股文quals

2009-12-08 15:19:58

WCF大數據量

2018-07-11 20:07:06

數據庫MySQL索引優(yōu)化
點贊
收藏

51CTO技術棧公眾號