806 字
约 2 分钟
7
S08-J01 · 分页:PageHelper vs MP 分页插件
适用读者:写过
limit但没想过"插件怎么改 SQL"的人。
前置:S08-B05。
实测环境:MyBatis-Plus 3.5.7 / H2(2026-11-05)。
覆盖旧文:904(85) 1179(80) 1180(58) + 空壳 1145 补写 = 223 点。
覆盖扩展:E-S08-004(limit 深翻慢)、E-S08-011(空壳 1145 分页,已补写)。
上一篇:S08-B05 · Wrapper 条件构造器
下一篇:S08-J02 · 插件链。
1. 一句话结论
分页插件不是"帮你查数据",是"拦截你的 SQL,自动加 LIMIT,并额外发一条 COUNT"。
实测(MP 分页 page=1,size=1):
==> Preparing: SELECT COUNT(*) AS total FROM sys_user WHERE deleted = 0
==> Preparing: SELECT id,user_name,age,deleted,version FROM sys_user WHERE deleted=0 ORDER BY id ASC LIMIT ?
6. 分页 page=1,size=1 → 记录数 1, total=2, pages=2
两条 SQL(count + list),LIMIT ? 是参数化的。
2. 两种实现
| 方案 | 机制 | 特点 |
|---|---|---|
| PageHelper(MyBatis) | 拦截 Executor.query,改写 SQL 加 limit |
需 startPage(),有"线程变量"风险 |
| MP 分页插件 | PaginationInnerInterceptor |
与 Page 对象天然结合 |
PageHelper 的坑:PageHelper.startPage() 是基于 ThreadLocal 的——如果后面紧跟的不是分页查询(或异步执行),会"分页错位"。MP 的 Page 参数化方式更安全。
3. LIMIT 深翻为什么慢(E-S08-004)
select * from t order by id limit 1000000, 20; -- 要扫 100 万行再丢弃
| 方案 | 做法 | 代价 |
|---|---|---|
| 深翻 | limit offset, size |
offset 越大越慢 |
| 游标分页(seek) | where id > lastId order by id limit 20 |
✅ O(1) 定位 |
| 延迟关联 | join (select id ... limit ...) |
减少回表 |
判据:"用户会翻到第 100 页吗?" 会 → 用游标分页;不会 → 普通 limit 够用。
生产上的分页几乎都是"前几页"——为深翻做的优化常是过度设计,但要有兜底(如游标)。
4. 分页的四个注意点
| 点 | 说明 |
|---|---|
| count 也要走索引 | count 查询慢会拖累整个分页 |
| 排序字段必须有索引 | 否则 order by 全表排 |
total 可关闭 |
不需要总数时(如移动端下拉)关掉省一次查询 |
| 分页大小上限 | 防止 size=100000 拖垮数据库 |
5. 五个误区
| 误区 | 真相 |
|---|---|
| "分页插件只发一条 SQL" | 通常两条(count + list) |
| "offset 大只是慢一点" | 是线性变慢 |
| "count 一定快" | 复杂 where 下可能比 list 还慢 |
| "PageHelper 全局无副作用" | ThreadLocal 有错位风险 |
| "分页大小随便传" | 需服务端限流上限 |
6. 自检
- 分页插件实际发几条 SQL?各是什么?
- PageHelper 的 ThreadLocal 风险是什么?
- 深翻为什么慢?三种优化方案?
- count 查询可能成为瓶颈吗?
- 为什么分页大小必须限制上限?
7. 下一篇
S08-J02 · 插件与拦截器链
分页讲完,下一篇讲"插件到底能拦哪四处":Executor/StatementHandler/ParameterHandler/ResultSetHandler。
本篇属于系列《S08 · MyBatis 持久层》。旧文来源:A-904/1179/1180(空壳 1145 补写);扩展点 E-S08-004。count+limit 两条 SQL 为 MP 3.5.7 实测。
S08-J01 · 分页:PageHelper vs MP 分页插件
https://www.clxhxhhr.top/posts/5287/ 评论
0 条
还没有评论,先写一条吧。