大数跨境
0
0

分页查询的优化方法(MySQL 高性能分页技巧)

分页查询的优化方法(MySQL 高性能分页技巧) Linux运维技术之路
2025-11-22
0
导读:分页查询的优化方法(MySQL 高性能分页技巧)

 










 

分页查询的优化方法(MySQL 高性能分页技巧)

分页在项目中非常常见,例如:


   
    
   SELECT * FROM article ORDER BY id LIMIT 1000000, 10;

但越往后翻页,性能越差:

  • • MySQL 会扫描 前 100 万行 丢弃掉
  • • 只返回最后 10 行
  • • 导致 CPU 飙升、耗时高、IO 大

下面总结 最常用、最有效的分页优化方法


一、避免深分页:使用索引字段做“记号分页”

这是最推荐,也是互联网公司最常用的方式。

原 SQL:


   
    
   LIMIT 1000000, 10

优化:使用上次的最大 id 继续往后查


   
    
   SELECT * FROM article 
WHERE
 id > last_id 
ORDER
 BY id 
LIMIT 10;

优点:

✔ 不扫描前面的数据
✔ 不会随着页数变大而变慢
✔ 尤其适合时间流、日志流、推文流

最适合以下场景:

  • • 上拉加载更多
  • • 无限滚动
  • • 移动端 feed 流

二、使用覆盖索引(减少回表)

深分页最大成本 = 扫描 + 回表。

例如:


   
    
   SELECT * FROM article ORDER BY id LIMIT 100000, 10;

优化方式:


   
    
   SELECT id FROM article ORDER BY id LIMIT 100000, 10;

然后再根据 id 去主键表查:


   
    
   SELECT * FROM article WHERE id IN (...);

这种方式叫 二次查询法,优点:

✔ 首次扫描使用覆盖索引,速度极快(不用回表)
✔ 第二次只查 10 条,非常轻量


三、使用“子查询 + join”优化深分页

经典分页优化:


   
    
   SELECT * FROM article 
WHERE
 id IN (
    SELECT
 id FROM article 
    ORDER
 BY id LIMIT 100000, 10
);

或使用 join:


   
    
   SELECT a.*
FROM
 article a
JOIN
 (
    SELECT
 id 
    FROM
 article 
    ORDER
 BY id 
    LIMIT 100000, 10
) b ON a.id = b.id;

子查询 LIMIT 使用覆盖索引,性能极高。


四、限制可访问分页深度(后台管理常用)

例如限制为 1000 页:


   
    
   if (page > 1000) {
    return
 error("不支持更深分页");
}

Pinterest / Instagram 等都使用类似策略:
避免用户翻 50 万页,本质没意义,也非常耗资源。


五、提前过滤减少数据量

例如:

原分页:


   
    
   SELECT * FROM order LIMIT 1000000, 10;

可以加上条件:


   
    
   SELECT * FROM order
WHERE
 create_time >= '2023-01-01'
ORDER
 BY id
LIMIT 10;

减少扫描量,就能减少分页成本。


六、使用延迟关联(最推荐的深分页终极优化)

延迟关联 = 先用索引查主键,再与主表 join

例子:


   
    
   SELECT * 
FROM
 article a 
JOIN
 (
    SELECT
 id 
    FROM
 article 
    WHERE
 status=1
    ORDER
 BY id
    LIMIT 1000000, 10
) t 
ON
 a.id = t.id;

延迟关联的特点:

✔ 子查询能用覆盖索引
✔ 不用扫描大表的所有列
✔ 主表只读取 10 行

实际效果:
100 万页从几秒降到几十毫秒。


七、使用倒排分页(从后往前查)

如果用户只看最后几页,可以:


   
    
   SELECT * 
FROM
 article 
ORDER
 BY id DESC 
LIMIT 10;

这个是高效的,不是深分页。
只要不是 OFFSET 大,MySQL 就快。


八、缓存分页接口(特别是热门页)

例如 Redis:

  • • 第 1 页数据固定最热门,完全可以缓存
  • • 某些榜单分页可以整体缓存

缓存可以让分页查询直接变成 O(1)。


九、使用搜索引擎或 ES(超大量数据)

当数据量达到千万级甚至亿级,MySQL 分页本身就不是最佳方案。

通常改用:

  • • Elasticsearch
  • • Solr
  • • ClickHouse
  • • OLAP 系统

这些系统分页查找更高效。


总结

1、深分页之所以慢,是因为 MySQL 会扫描大量不需要的数据。
2、 核心优化思路就是 减少扫描 + 避免回表

3、 最有效的方法是:
游标分页(id > last_id) + 覆盖索引 + 延迟关联

 




 

 


往期回顾


【声明】内容源于网络
0
0
Linux运维技术之路
专注运维架构、高可用、高并发、高性能、大数据、容器化、数据库、python、devops等开源技术和实践的分享。
内容 347
粉丝 0
Linux运维技术之路 专注运维架构、高可用、高并发、高性能、大数据、容器化、数据库、python、devops等开源技术和实践的分享。
总阅读675
粉丝0
内容347