MySQL LIMIT 深分頁(yè)性能問(wèn)題與優(yōu)化實(shí)戰(zhàn)
一、題目回顧
執(zhí)行語(yǔ)句如下:
SELECT * FROM orders LIMIT 100, 100;
意思是:
跳過(guò)前 100 行,取接下來(lái)的 100 行。
二、MySQL 的執(zhí)行邏輯
MySQL 的 LIMIT offset, count 實(shí)際執(zhí)行流程是這樣的:
- 從結(jié)果集的開(kāi)頭開(kāi)始掃描;
- 一直取到 offset + count 條;
- 扔掉前
offset條; - 返回后面的
count條給客戶端。
?? 換句話說(shuō):
MySQL 必須先掃描 offset + count 行數(shù)據(jù), 再丟棄 offset 行,只返回 count 行。
三、代入具體數(shù)字
你的 SQL:
LIMIT 100, 100
即:
- offset = 100
- count = 100
那么 MySQL 實(shí)際上會(huì)掃描 200 行:
掃描 200 行 → 丟掉前 100 行 → 返回 100 行。
四、更大的偏移量時(shí)的問(wèn)題
假設(shè)語(yǔ)句:
SELECT * FROM orders LIMIT 1000000, 100;
MySQL 依然會(huì):
- 掃描前 1,000,100 行;
- 丟掉前 1,000,000 行;
- 僅返回最后的 100 行。
?? 性能問(wèn)題:
- offset 越大,浪費(fèi)越多;
- MySQL 沒(méi)有“從第 N 條開(kāi)始讀取”的索引級(jí)跳轉(zhuǎn)機(jī)制;
- 所以分頁(yè)越深,查詢?cè)铰?/li>
五、為什么 MySQL 要這么干?
MySQL 的執(zhí)行計(jì)劃是基于結(jié)果集順序的:
- 沒(méi)有 offset 索引直接跳過(guò)功能;
- 除非你手動(dòng)提供一個(gè)有序字段(如自增 id 或時(shí)間戳);
- 否則它必須遍歷前 offset 行,才能保證返回結(jié)果的排序正確。
六、如何優(yōu)化深分頁(yè)?
方法 1:基于主鍵或排序字段“范圍分頁(yè)”
例如原語(yǔ)句:
SELECT * FROM orders ORDER BY id LIMIT 1000000, 100;
可以改為:
SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 100;
這樣 MySQL 可以用索引定位到 id=1000001 的位置,然后順序掃描 100 行,性能極快。
方法 2:記錄上次分頁(yè)的“游標(biāo)位置”
前端分頁(yè)時(shí)保存最后一條記錄的 ID:
-- 第一次查詢
SELECT * FROM orders ORDER BY id LIMIT 100;
-- 第二頁(yè)查詢
SELECT * FROM orders WHERE id > {last_id_of_prev_page} ORDER BY id LIMIT 100;
這叫 Keyset Pagination(基于鍵的分頁(yè)),
可以避免深度偏移,尤其適合滾動(dòng)加載、無(wú)限下拉列表等場(chǎng)景。
方法 3:子查詢 + JOIN 減少數(shù)據(jù)傳遞量(部分場(chǎng)景)
SELECT o.* FROM orders o JOIN ( SELECT id FROM orders ORDER BY id LIMIT 1000000, 100 ) t ON o.id = t.id;
- 子查詢只拿 ID(輕量);
- 再 JOIN 原表獲取完整行;
- 比直接
LIMIT效率更好。
七、結(jié)論總結(jié)
| 語(yǔ)句 | 實(shí)際掃描行數(shù) | 返回行數(shù) | 特點(diǎn) |
|---|---|---|---|
| LIMIT 100, 100 | 200 行 | 100 行 | 小偏移量,影響可忽略 |
| LIMIT 1000000, 100 | 1,000,100 行 | 100 行 | ?? 深分頁(yè),極慢 |
| WHERE id > x LIMIT 100 | 100 行 | 100 行 | ? 推薦分頁(yè)方式 |
八、總結(jié)
MySQL 的 LIMIT offset, count 會(huì)掃描 offset + count 行,返回 count 行。
當(dāng) offset 很大時(shí),性能急劇下降,建議用基于主鍵的范圍分頁(yè)(Keyset Pagination) 代替。
到此這篇關(guān)于MySQL LIMIT 深分頁(yè)性能問(wèn)題與優(yōu)化實(shí)戰(zhàn)的文章就介紹到這了,更多相關(guān)MySQL LIMIT 深分頁(yè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql MGR 單主多主模式切換知識(shí)點(diǎn)詳解
在本篇文章里小編給大家整理了關(guān)于mysql MGR 單主多主模式切換知識(shí)點(diǎn)詳解內(nèi)容,需要的朋友們可以參考下。2020-03-03
MySQL使用UNIQUE實(shí)現(xiàn)數(shù)據(jù)不重復(fù)插入
當(dāng)unique列在一個(gè)UNIQUE鍵上插入包含重復(fù)值的記錄時(shí),我們可以控制MySQL如何處理這種情況:使用IGNORE關(guān)鍵字或者ON DUPLICATE KEY UPDATE子句跳過(guò)INSERT、中斷操作或者更新舊記錄為新值。2017-05-05
sql獲得當(dāng)前時(shí)間以及SQL比較時(shí)間大小詳解
最近寫項(xiàng)目的時(shí)候功能需要在sql語(yǔ)句中獲取當(dāng)前時(shí)間,所以下面這篇文章主要給大家介紹了關(guān)于sql獲得當(dāng)前時(shí)間以及SQL比較時(shí)間大小的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04
windows下安裝mysql8.0.18的教程(社區(qū)版)
本文章簡(jiǎn)單介紹一下mysql在windows下的安裝方式,主要介紹了mysql社區(qū)版8.0.18版本,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2020-01-01
MySQL與PHP的基礎(chǔ)與應(yīng)用專題之索引
MySQL是一個(gè)關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),由瑞典MySQL?AB?公司開(kāi)發(fā),屬于?Oracle?旗下產(chǎn)品。MySQL?是最流行的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)之一,本系列將帶你掌握php與mysql的基礎(chǔ)應(yīng)用,本篇從索引開(kāi)始2022-02-02

