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 相关文章推荐
MySQL学习总结-基础架构概述
Apr 05 MySQL
MySQL性能压力基准测试工具sysbench的使用简介
Apr 21 MySQL
浅谈MySQL user权限表
Jun 18 MySQL
MySQL系列之十 MySQL事务隔离实现并发控制
Jul 02 MySQL
MySQL 聚合函数排序
Jul 16 MySQL
面试被问select......for update会锁表还是锁行
Nov 11 MySQL
MySQL 主从复制数据不一致的解决方法
Mar 18 MySQL
Innodb存储引擎中的后台线程详解
Apr 03 MySQL
解决Mysql中的innoDB幻读问题
Apr 29 MySQL
MySQL 数据 data 基本操作
May 04 MySQL
mysql sql常用语句大全
Jun 21 MySQL
MySQL数据库表约束讲解
Jun 21 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下防止单引号,双引号在接受页面转义的设置方法
2008/09/25 PHP
php 截取字符串并以零补齐str_pad() 函数
2011/05/07 PHP
PHP资源管理框架Assetic简介
2014/06/12 PHP
php实现的常见排序算法汇总
2014/09/08 PHP
php实现utf-8转unicode函数分享
2015/01/06 PHP
PHP使用fopen与file_get_contents读取文件实例分享
2016/03/04 PHP
PHP使用PDO操作数据库的乱码问题解决方法
2016/04/08 PHP
日期函数扩展类Ver0.1.1
2006/09/07 Javascript
jQuery 各种浏览器下获得日期区别
2008/12/22 Javascript
一些mootools的学习资源
2010/02/07 Javascript
了解一点js的Eval函数
2012/07/26 Javascript
js解析与序列化json数据(二)序列化探讨
2013/02/01 Javascript
利用jQuery的deferred对象实现异步按顺序加载JS文件
2013/03/17 Javascript
Javascript四舍五入Math.round()与Math.pow()使用介绍
2013/12/27 Javascript
JavaScript实现动态添加,删除行的方法实例详解
2015/07/02 Javascript
学习javascript面向对象 javascript实现继承的方式
2016/01/04 Javascript
浅谈toLowerCase和toLocaleLowerCase的区别
2016/08/15 Javascript
js原生日历的实例(推荐)
2017/10/31 Javascript
React.js绑定this的5种方法(小结)
2018/06/05 Javascript
vue3.0 CLI - 2.3 - 组件 home.vue 中学习指令和绑定
2018/09/14 Javascript
VUE搭建手机商城心得和遇到的坑
2019/02/21 Javascript
TensorFlow实现MLP多层感知机模型
2018/03/09 Python
Tensorflow之Saver的用法详解
2018/04/23 Python
python实现转盘效果 python实现轮盘抽奖游戏
2019/01/22 Python
python selenium firefox使用详解
2019/02/26 Python
基于TensorBoard中graph模块图结构分析
2020/02/15 Python
PyCharm+Pipenv虚拟环境开发和依赖管理的教程详解
2020/04/16 Python
python 根据列表批量下载网易云音乐的免费音乐
2020/12/03 Python
亚洲领先的旅游体验市场:Voyagin
2019/11/23 全球购物
计算机开发个人求职信范文
2013/09/26 职场文书
解除合同协议书
2014/04/17 职场文书
上班时间打瞌睡检讨书
2014/09/26 职场文书
小学音乐课教学反思
2016/02/18 职场文书
JavaScript异步操作中串行和并行
2021/11/20 Javascript
vue项目打包后路由错误的解决方法
2022/04/13 Vue.js
MySQL 自动填充 create_time 和 update_time
2022/05/20 MySQL