场景引入:
凌晨3点,你盯着屏幕上的进度条,一个简单的分页查询转了15秒还没结果,咖啡杯已经空了第3次...💀 这可能是每个后端开发都经历过的噩梦,别慌!今天我们就来彻底解决MySQL分页这个"性能杀手"!
典型的LIMIT offset, size
分页(比如LIMIT 10000, 20
)在数据量大时会暴露致命问题:
-- 灾难性写法(数据量10万+时性能骤降) SELECT * FROM orders ORDER BY create_time DESC LIMIT 50000, 20;
核心思想:用上一页的最后一条记录作为起点
-- 第一页(常规查询) SELECT * FROM orders WHERE status = 'paid' ORDER BY id DESC LIMIT 20; -- 后续页(假设上一页最后一条id=520) SELECT * FROM orders WHERE status = 'paid' AND id < 520 -- 关键点! ORDER BY id DESC LIMIT 20;
优势:
id
和status
有联合索引) 当表中有TEXT/BLOB
等大字段时:
SELECT t.* FROM orders t JOIN ( SELECT id FROM orders WHERE user_id = 123 ORDER BY create_time DESC LIMIT 10000, 20 ) tmp ON t.id = tmp.id; -- 先定位ID,再回表
原理:
适合数据变化不频繁的场景:
-- 建立分页辅助表 CREATE TABLE order_page_meta ( page_num INT PRIMARY KEY, min_id INT, max_id INT ); -- 查询时直接定位范围 SELECT * FROM orders WHERE id BETWEEN (SELECT min_id FROM order_page_meta WHERE page_num=5) AND (SELECT max_id FROM order_page_meta WHERE page_num=5);
UUID作为主键时,常规分页会非常痛苦:
优化方案:
(uuid, id)
-- 先获取锚点UUID SELECT uuid FROM items ORDER BY uuid LIMIT 10000, 1; -- 再用锚点查询 SELECT * FROM items WHERE uuid > '刚才查到的UUID' ORDER BY uuid LIMIT 20;
当单表数据超过500万时:
-- 按时间分片示例 SELECT * FROM orders WHERE create_time >= '2025-01-01' AND create_time < '2025-02-01' ORDER BY id DESC LIMIT 20;
关键点:
方案 | 10万数据耗时 | 500万数据耗时 |
---|---|---|
传统LIMIT分页 | 1200ms | 超时(>30s) |
游标分页 | 15ms | 18ms |
延迟关联 | 45ms | 200ms |
UUID优化方案 | 80ms | 300ms |
SQL_CALC_FOUND_ROWS
:这个魔法计数比二次查询还慢 ORDER BY RAND()
:随机排序是大规模分页的死刑判决 记住这个选择树:
你可以把那个凌晨3点的咖啡杯收起来了——优化后的分页查询,快到能让你的鼠标指针跟不上!⚡
(注:本文测试数据基于MySQL 8.0.33,InnoDB引擎,2025年验证)
本文由 令狐夏旋 于2025-07-31发表在【云服务器提供商】,文中图片由(令狐夏旋)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/498261.html
发表评论