深度分页性能差本质是需扫描跳过大量数据,优化核心是避免OFFSET全量扫描,推荐游标分页(基于主键/时间戳)、覆盖索引+子查询、分表归档、分页缓存等方案。
深度分页(比如 OFFSET 1000000 LIMIT 20)在 MyS

OFFSET 的全量扫描,改用基于有序字段的“游标分页”或覆盖索引+子查询等更高效方式。
适用于数据按主键或时间戳等单调递增字段排序、且前端支持“上一页/下一页”而非跳转任意页的场景。例如按 id 升序分页:
SELECT * FROM orders ORDER BY id LIMIT 20,记下最后一条的 id = 12345
SELECT * FROM orders WHERE id > 12345 ORDER BY id LIMIT 20
SELECT id FROM orders ORDER BY id LIMIT 1 OFFSET 999999 获取锚点 ID(仍慢),再用游标查,但仅限低频操作当必须用 OFFSET 时,先通过覆盖索引快速定位主键,再关联原表取完整数据:
SELECT id, name, created_at FROM users ORDER BY created_at LIMIT 20 OFFSET 100000
SELECT u.* FROM users u INNER JOIN (SELECT id FROM users ORDER BY created_at LIMIT 20 OFFSET 100000) t ON u.id = t.id
created_at + id 组合索引),体积小、扫描快;外层 JOIN 避免大量回表(created_at, id) 这类联合索引,且 id 在索引末尾(保证排序稳定性)对历史数据占比高、访问集中在近期的业务(如订单、日志),深度分页慢往往是因为单表过大:
orders_archive 表,主表保持百万级规模users_001 ~ users_100,配合路由规则,让单表数据量可控对固定条件(如“按销量排行 TOP 10000”)的深度分页,可预计算并缓存结果:
SELECT id FROM products ORDER BY sales DESC,按每页 20 条切分成 Redis 中的 zset 或 hashZRANGE products_top_sales 999980 999999 拿 ID 列表,再批量查详情