温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

分页查询如何用索引扫描

发布时间:2026-09-09 08:10:33 来源:亿速云 阅读:114 作者:小樊 栏目:数据库

在关系型数据库中,分页查询(LIMIT/OFFSET)如果不用索引,往往会变成“先全表扫描、再丢弃前面记录”,随着 OFFSET 变大,性能急剧下降。
“用索引扫描做分页”的核心思想是:让数据库通过索引直接定位起始位置,而不是扫描并跳过大量行。

下面按常见场景说明。


一、最基础:ORDER BY + 索引

SELECT id, name
FROM user
ORDER BY id
LIMIT 10 OFFSET 1000;

问题

  • 即使 id 是主键,MySQL 等数据库仍可能:
    • 扫描前 1010 行
    • 丢弃前 1000 行
  • OFFSET 越大越慢

改进:索引覆盖 + 排序一致

确保:

  • ORDER BY 的列有索引
  • 排序方向一致(ASC/DESC)
  • 查询字段能被索引覆盖(避免回表)
-- id 是主键索引
SELECT id
FROM user
ORDER BY id
LIMIT 10 OFFSET 1000;

二、游标分页(推荐,真正用索引扫描)

也叫 Keyset Pagination / Seek Method

原理

不跳过记录,而是从某个索引值之后开始扫

-- 上一页最后一条记录的 id
SELECT id, name
FROM user
WHERE id > 1000
ORDER BY id
LIMIT 10;

✅ 优点:

  • 走 PRIMARY / INDEX RANGE SCAN
  • 不依赖 OFFSET
  • 性能稳定(百万、千万级都快)

✅ 执行计划通常是:

Index Range Scan

三、复合索引分页(多字段排序)

ORDER BY create_time DESC, id DESC

建索引

CREATE INDEX idx_user_ct_id
ON user(create_time, id);

分页查询

SELECT id, create_time
FROM user
WHERE (create_time, id) < ('2024-01-01 10:00:00', 5000)
ORDER BY create_time DESC, id DESC
LIMIT 10;

不同数据库语法略有差异(MySQL 8 / PostgreSQL 支持元组比较)


四、避免“索引失效”的常见坑

❌ 以下会导致索引无法用于分页:

  • ORDER BY 字段无索引
  • ORDER BY 多字段顺序不一致
  • 使用函数:
    ORDER BY DATE(create_time)
    
  • 隐式类型转换
  • OFFSET 极大但无游标

五、对比总结

方式 是否用索引扫描 OFFSET 变大 推荐度
LIMIT OFFSET 可能全表 越来越慢 ❌
索引 ORDER BY 部分 仍慢 ⚠️
游标分页 ✅ 索引范围扫描 稳定 ✅✅✅

六、一句话结论

分页要用索引扫描,就不要用 OFFSET,而要用“上次最大索引值”做范围查询。

如果你用的是 MySQL / PostgreSQL / Oracle,或者有特殊业务(复合排序、联表分页),可以告诉我,我可以给你针对性 SQL。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手