MySQL 8.0的ROW_NUMBER()窗口函数怎么解决分页性能瓶颈?

酷静酱_4400

酷静酱_4400

2026-07-07

265人浏览

原创

row_number()分页不比limit快,因其本身仅打标,真正提速需排序走索引、中间集可控、过滤尽早发生;错误用法如无索引order by、where中直接引用rn、未含主键导致序号不稳定、窗口外未过滤等会严重拖慢性能。

mysql 8.0的row_number()窗口函数怎么解决分页性能瓶颈?

为什么ROW_NUMBER()分页不比LIMIT快?

它本身不快,快的是你用对了方式。ROW_NUMBER()只是给每行打标,真正提速靠的是避免OFFSET逐行跳过——但前提是排序走索引、中间结果集不爆炸、别在WHERE里直接引用ROW_NUMBER()。

  • EXPLAIN里看到Using temporary; Using filesort,说明ORDER BY字段没索引,窗口函数白搭
  • WHERE rn > 1000000 LIMIT 20写法错误:MySQL不允许在同级WHERE中引用窗口别名,必须套CTE或子查询
  • 没加主键到ORDER BY里(比如只写ORDER BY create_time DESC),时间相同会导致rn分配不稳定,翻页重复或漏数据
  • WHERE条件写在窗口外(如CTE里过滤status='done'),否则窗口会先算全表再过滤,内存压力翻倍

怎么写才能真提速?

核心是让排序可下推、中间集可控、过滤尽早发生。不是套个ROW_NUMBER()就完事。

  • 用CTE结构:
    WITH ranked AS (
      SELECT id, name, create_time,
             ROW_NUMBER() OVER (ORDER BY create_time DESC, id ASC) AS rn
      FROM orders 
      WHERE status = 'shipped'
    )
    SELECT id, name, create_time FROM ranked 
    WHERE rn BETWEEN 100001 AND 100020;
  • ORDER BY必须含索引列组合:建复合索引INDEX (status, create_time, id),让WHERE+ORDER BY一起走索引
  • 别用PARTITION BY做普通分页——它会让ROW_NUMBER()按组重编号,全局序号就乱了
  • 页码参数要转成BETWEEN范围,注意整数溢出:($page - 1) * $size + 1可能超BIGINT,尤其$size=10000、$page=100000时

什么情况下它反而更慢?

不是所有分页都适合换。当你的瓶颈不在OFFSET,而在排序本身时,ROW_NUMBER()只会雪上加霜。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
  • 数据量小(LIMIT 1000, 20比CTE+窗口快得多,少一次全排序
  • ORDER BY字段无索引:引擎被迫磁盘排序,Using filesort耗时远超OFFSET扫描
  • 内存受限(如RDS 2GB规格):千万行打标需要缓存全部排序结果,OOM风险高
  • 实时性要求极高:窗口基于事务快照,两次查询间若新插入数据,rn会变,但页面内容可能“跳帧”

游标分页才是千万级的正解

真要撑住千万级,别纠结ROW_NUMBER()和LIMIT谁更快——它们都扛不住随机跳页。该换思路。

  • 记录上一页最后一条的(create_time, id),下一页用:
    WHERE (create_time, id) > ('2025-06-01', 9999999)
    ORDER BY create_time DESC, id ASC
    LIMIT 20
  • 这个WHERE能走联合索引,完全避开排序和打标开销
  • 后台管理需要跳第1000页?预生成锚点表:每10000行存一次首个id,查页时先查锚点再LIMIT
  • MySQL 8.0的ROW_NUMBER()仍是伪窗口函数,底层依赖临时表;别把它当PostgreSQL或SQL Server那样信任执行计划

实际线上跑千万级订单表,游标分页QPS稳定在1200+,而ROW_NUMBER()分页在第500页后开始抖动,EXPLAIN FORMAT=TREE里WindowAgg节点占比超70%——这时候再调索引也没用,得切访问模式。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

mysql mysql 8.0 性能瓶颈

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4263

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

891

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1109

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6181

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3023

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6160

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8301

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1130

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

992

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 187人学习