分页和 Join 优化的目标不是消灭某个语法,而是让数据库尽早缩小候选行,并减少排序、临时结果、回表和网络返回。
Table of contents
Open Table of contents
深分页为什么越来越慢
SELECT id FROM orders ORDER BY id LIMIT 900000, 20;
数据库通常仍要读取并丢弃前 900000 行。寻页分页(也叫 Keyset Pagination)保存上次最后一行的稳定游标:
SELECT id FROM orders
WHERE id > :last_id
ORDER BY id
LIMIT 20;
它不能随意跳到第 N 页,但复杂度更稳定。排序键必须唯一且方向固定;若按 created_at 排序,应附加 id 作为并列裁决,并用 (created_at, id) 组成游标。
OrderMapper.seekPage下载给出了 Java 映射。
排序何时能利用索引
筛选与排序顺序和联合索引一致时,数据库可按索引顺序输出。混合升降序、前导列缺失、对列做函数运算或排序跨多张表,都可能需要额外排序。不要因为看到 filesort 就盲目建索引,先看排序行数和总耗时。
Join 与子查询没有固定胜负
现代优化器可能把 EXISTS、IN 或派生表改写为半连接等计划。真正要看的是:连接键有无索引、过滤能否提前、估算是否准确、驱动侧结果是否足够小。
一对多 Join 会重复父表列。若只判断“是否存在”,EXISTS 比 Join 后 DISTINCT 更清楚;若确实需要子项,Join 或分批查询都应测量返回字节和组装成本。
验证清单
用不同参数分布测试第一页、中间页和尾页;比较扫描行数而非只看返回 20 行;确认并发插入下没有重复或漏项;对 Join 记录每步实际行数。实验脚本同时包含 OFFSET 与寻页计划,便于对照。
下一步
继续阅读06-09 ACID 与隔离级别,从单条查询进入并发事务。