薛晓刚-
踩坑!数据库分页 LIMIT 100,200 居然查了 300 行?90% 开发都中招
原创
关注作者
腾讯云
开发者社区
文档
建议反馈
控制台
登录/注册
首页
学习
活动
专区
圈层
工具
MCP广场
文章/答案/技术大牛
搜索
搜索
关闭
发布
薛晓刚-
社区首页
>
专栏
>
踩坑!数据库分页 LIMIT 100,200 居然查了 300 行?90% 开发都中招
踩坑!数据库分页 LIMIT 100,200 居然查了 300 行?90% 开发都中招
原创
薛晓刚-
关注
发布于 2025-11-04 20:33:44
发布于 2025-11-04 20:33:44
166
0
举报
这个案例其实是在我写完第一本书后遇到的,所以也一直没写
日常开发中,分页查询是高频操作 —— 列表页一页页往下翻、批量导出数据分批拉取,我们早已习惯用 LIMIT(MySQL)或类似语法(Oracle)实现。但很多人不知道:LIMIT 200,100 不是直接查 100 行,而是先查 300 行再丢弃前 200 行!
如果开发用循环分页批量取数(比如每次取 100 行,循环 10 次),以为总共只查 1000 行,实际可能查了几万行,数据量越大性能越崩。今天 MySQL 8.0 做实测(其实Oracle和PostgreSQL也一样,因为这是数据库基本原理),带你看清这个隐藏误区。
我有一个1万行的表(真实环境可能是会大一些比如1000万,我们这里用1:1000的比例缩放一下)
image.png
image.png
可以看到这个SQL查了10行返回10行。
image.png
image.png
可以看到这个SQL查了20行返回10行。
所以以此类推
image.png
image.png
可以看到这个SQL查了30行返回10行。
主观上以为是10行10行的分段取数,实际上是叠加。
这个的计算公式应该是:S = k × (size + k×size) ÷ 2 = size × k × (k + 1) ÷ 2
总扫描行数 S = 项数 × (首项 + 末项) ÷ 2
如果每页10行按照这种错误的方式导出数据则是:循环 10 次(k=10,size=100)
S = 100 × 10 × (10 + 1) ÷ 2 = 100 × 10 × 11 ÷ 2 = 5500 行
结论以为读取了100行下载了100行,实际是读取了5500行下载了100行。是55倍的关系。
而一开始我说了,本案例的比例尺是1:1000。这里的5500行实际上可能是5500000。
当然这里还是只循环10次,如果是循环100次呢?
所以分页本身没有错,但是如果说用这种方法去下载大可不必了
语法直觉误导:LIMIT offset, size 看起来像「直接跳过 offset 行,取 size 行」,但数据库无法直接「跳过」,只能先扫描到 offset+size 行,再丢弃前 offset 行;
下载那就select 结果集一次性获取吧。如果一次性实在很大。那么就指定好一些条件,比如时间等,分批下载。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系
cloudcommunity@tencent.com
删除。
数据库
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系
cloudcommunity@tencent.com
删除。
数据库
评论
登录
后参与评论
0 条评论
热度
最新
推荐阅读
目录
这个案例其实是在我写完第一本书后遇到的,所以也一直没写
我有一个1万行的表(真实环境可能是会大一些比如1000万,我们这里用1:1000的比例缩放一下)
主观上以为是10行10行的分段取数,实际上是叠加。
所以分页本身没有错,但是如果说用这种方法去下载大可不必了
领券
问题归档
专栏文章
快讯文章归档
关键词归档
开发者手册归档
开发者手册 Section 归档
0
0
0
推荐