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 07 MySQL
MySQL性能压力基准测试工具sysbench的使用简介
Apr 21 MySQL
MySql学习笔记之事务隔离级别详解
May 12 MySQL
Mysql数据库索引面试题(程序员基础技能)
May 31 MySQL
MySQL REVOKE实现删除用户权限
Jun 18 MySQL
MySQL系列之十一 日志记录
Jul 02 MySQL
MySQL 四种连接和多表查询详解
Jul 16 MySQL
MySQL中datetime时间字段的四舍五入操作
Oct 05 MySQL
mysql 排序失效
May 20 MySQL
MySQL选择合适的备份策略和备份工具
Jun 01 MySQL
MySQL的表级锁,行级锁,排它锁和共享锁
Jul 15 MySQL
MySQL实现用逗号进行拼接、以逗号进行分割
Dec 24 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中foreach循环中使用引用要注意的地方
2011/01/02 PHP
PHP详解ASCII码对照表与字符转换
2011/12/05 PHP
php实现redis数据库指定库号迁移的方法
2015/01/14 PHP
php根据一个给定范围和步进生成数组的方法
2015/06/19 PHP
php搜索文件程序分享
2015/10/30 PHP
Yii2基于Ajax自动获取表单数据的方法
2016/08/10 PHP
PHP面向对象程序设计之接口的继承定义与用法详解
2018/12/20 PHP
jQuery 阴影插件代码分享
2012/01/09 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
2016/05/30 Javascript
Bootstrap的fileinput插件实现多文件上传的方法
2016/09/05 Javascript
利用JS实现页面删除并重新排序功能
2016/12/09 Javascript
Bootstrap 过渡效果Transition 模态框(Modal)
2017/03/17 Javascript
EasyUI Datebox 日期验证之开始日期小于结束时间
2017/05/19 Javascript
jQuery获取单选按钮radio选中值与去除所有radio选中状态的方法
2017/05/20 jQuery
基于JavaScript实现一个简单的Vue
2018/09/26 Javascript
微信小程序Echarts覆盖正常组件问题解决
2019/07/13 Javascript
Vue 权限控制的两种方法(路由验证)
2019/08/16 Javascript
详解基于Vue的支持数据双向绑定的select组件
2019/09/02 Javascript
微信小程序获取当前位置和城市名
2019/11/13 Javascript
JSONObject与JSONArray使用方法解析
2020/09/28 Javascript
python简单实现刷新智联简历
2016/03/30 Python
python matlibplot绘制3D图形
2018/07/02 Python
python 中如何获取列表的索引
2019/07/02 Python
在python Numpy中求向量和矩阵的范数实例
2019/08/26 Python
Python django框架输入汉字,数字,字符生成二维码实现详解
2019/09/24 Python
selenium中get_cookies()和add_cookie()的用法详解
2020/01/06 Python
python实现TCP文件传输
2020/03/20 Python
Python+PyQt5+MySQL实现天气管理系统
2020/06/16 Python
详解CSS3:overflow属性
2020/11/17 HTML / CSS
耐克奥地利官网:Nike奥地利
2019/08/16 全球购物
甜品店的创业计划书范文
2014/01/02 职场文书
大学生党员个人对照检查材料范文
2014/09/25 职场文书
安全伴我行主题班会
2015/08/13 职场文书
小学家庭教育心得体会
2016/01/14 职场文书
幼儿体育课教学反思
2016/02/16 职场文书
企业管理制度设计时要注意的几种“常见病”!
2019/04/19 职场文书