MySQL 分页查询的优化技巧


Posted in MySQL onMay 12, 2021

在有分页查询的应用中,包括 LIMIT 和 OFFSET 的查询十分常见,而且几乎每个都会有一个 ORDER BY 子句。如果使用索引排序的话将对性能优化十分有帮助,否则服务端需要做很多文件排序。

一个高频的问题是 offset 的值过大。如果查询类似 LIMIT 10000, 20,将会产生10020行,并将之前的10000行丢弃,这样的代价很高。假设所有的页使用相同的频次访问,这样的查询将平均扫描一半数据表。为了优化他们,你可以在分页视图中限制最多可访问的页数,或者让大便宜的查询更有效。

一个改善性能简单的技巧是在覆盖索引上进行查询操作而不是整行数据。你可以将结果与完整的行做一次联合然后再获取额外需要的列。这样的效率会更高,例如下面的查询:

SELECT film_id, description FROM sakila.film ORDER BY title LIMIT 50, 5;

如果数据表很大的话,则可以按下面的方式进行优化:

SELECT film.film_id, film.description
FROM sakila.film
	INNER JOIN (
    SELECT film_id FROM sakila.film
    ORDER BY title LIMIT 50, 5)
  ) as lim USING(film_id);

这种“推断联合查询”能够有效工作是因为它使用了索引减少了服务端尽可能少地访问数据行去检查数据。一旦复核要求的行查到了,将他们与对应的数据表的行进行联合查询以获取对应行的其他列。

有些时候也可以将 limit 转换为固定位置的查询,这种方式可以对索引进行范围扫描完成。例如,如果你预先计算一个固定位置的列 称之为 position,可以重写查询如下:

SELECT film_id, description FROM sakila.film
WHERE position BETWEEN 50 AND 54 ORDER BY position;

排序的数据也可以使用类似的方式解决,但是通常会被 GROUP BY操作影响。大部分情况下需要提前计算和存储排序值。

LIMIT 和 OFFSET 真正的问题是在OFFSET,这意味着服务端会把很多数据行丢弃。如果使用一个有序书签来记录下次获取行的位置的话,则可以从上次的位置开始访问接下来的数据。例如,如果你需要对出租记录进行分页,从最新的出租记录开始往回查询,则可以依赖于记录的主键是一直增加的,因此可以对第一页数据这样查询:

SELECT * FROM sakila.rental
ORDER BY rental_id DESC LIMIT 20;

这个查询返回16049到16030之间的数据。接下来的查询可以从之前结束位置开始:

SELECT * FROM sakila.rental
WHERE rental_id < 16030 
ORDER BY rental_id DESC LIMIT 20;

这个技巧不管你从多远的偏移值开始查询都是很有效的。

其他的一些技巧包括使用预先计算的统计值,或者通过联合冗余了主键和排序列的数据表进行查询,这两种方式都是通过空间换取时间的方式提高查询效率。

以上就是MySQL 分页查询的优化技巧的详细内容,更多关于MySQL 分页查询的优化的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
left join、inner join、right join的区别
Apr 05 MySQL
Mysql Show Profile
Apr 05 MySQL
MySQL表的增删改查基础教程
Apr 07 MySQL
MySQL 如何分析查询性能
May 12 MySQL
MySQL中使用or、in与union all在查询命令下的效率对比
May 26 MySQL
mysql 联合索引生效的条件及索引失效的条件
Nov 20 MySQL
Mysql外键约束的创建与删除的使用
Mar 03 MySQL
MySQL批量更新不同表中的数据
May 11 MySQL
MySQL聚簇索引和非聚簇索引的区别详情
Jun 14 MySQL
MySQL事务的隔离级别详情
Jul 15 MySQL
MySQL count(*)统计总数问题汇总
Sep 23 MySQL
MySql学习笔记之事务隔离级别详解
MySQL 分组查询的优化方法
May 12 #MySQL
JDBC连接的六步实例代码(与mysql连接)
May 12 #MySQL
MySQL索引知识的一些小妙招总结
MySQL COUNT函数的使用与优化
May 10 #MySQL
解读MySQL的客户端和服务端协议
MySQL 重写查询语句的三种策略
May 10 #MySQL
You might like
劣质的PHP代码简化
2010/02/08 PHP
php通过array_push()函数添加多个变量到数组末尾的方法
2015/03/18 PHP
PHP中foreach()用法汇总
2015/07/02 PHP
详解PHP中的PDO类
2015/07/06 PHP
php观察者模式应用场景实例详解
2017/02/03 PHP
php利用云片网实现短信验证码功能的示例代码
2017/11/18 PHP
php设计模式之正面模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
JavaScript入门教程(10) 认识其他对象
2009/01/31 Javascript
javascript操作cookie的文章(设置,删除cookies)
2010/04/01 Javascript
JS获取浏览器版本及名称实现函数
2013/04/02 Javascript
js中对象的声明方式以及数组的一些用法示例
2013/12/11 Javascript
深入学习JavaScript中的Rest参数和参数默认值
2015/07/28 Javascript
基于jQuery实现在线选座之高铁版
2015/08/24 Javascript
Javascript 计算字符串在localStorage中所占字节数
2015/10/21 Javascript
angularjs创建弹出框实现拖动效果
2020/08/25 Javascript
JS中的进制转换以及作用
2016/06/26 Javascript
js学习总结之DOM2兼容处理重复问题的解决方法
2017/07/27 Javascript
Vue 重置组件到初始状态的方法示例
2018/10/10 Javascript
JS扁平化输出数组的2种方法解析
2019/09/17 Javascript
ES6中的类(Class)示例详解
2020/12/09 Javascript
[35:34]Liquid vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python查询Mysql时返回字典结构的代码
2012/06/18 Python
python支持断点续传的多线程下载示例
2014/01/16 Python
Python贪心算法实例小结
2018/04/22 Python
解决python读取几千万行的大表内存问题
2018/06/26 Python
Matplotlib中文乱码的3种解决方案
2018/11/15 Python
Python图像处理之图像的缩放、旋转与翻转实现方法示例
2019/01/04 Python
linux下进程间通信的方式
2014/12/23 面试题
如何用Python来进行查询和替换一个文本字符串
2014/01/02 面试题
应届生高等护理求职信
2013/10/12 职场文书
项目开发计划书
2014/01/09 职场文书
同学聚会欢迎辞
2014/01/14 职场文书
植树节口号
2014/06/21 职场文书
2015年重阳节慰问信
2015/03/23 职场文书
小公司融资,商业计划书的8切记
2019/07/15 职场文书
Go语言空白表示符_的实例用法
2021/07/04 Golang