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 Show Profile
Apr 05 MySQL
MySQL sql_mode修改不生效的原因及解决
May 07 MySQL
正确使用MySQL update语句
May 26 MySQL
MySQL中的布尔值,怎么存储false或true
Jun 04 MySQL
探究Mysql模糊查询是否区分大小写
Jun 11 MySQL
mysql优化之query_cache_limit参数说明
Jul 01 MySQL
MySQL去除重叠时间求时间差和的实现
Aug 23 MySQL
SQL语法CONSTRAINT约束操作详情
Jan 18 MySQL
一条慢SQL语句引发的改造之路
Mar 16 MySQL
以MySQL5.7为例了解一下执行计划
Apr 13 MySQL
SQL语句多表联合查询的方法示例
Apr 18 MySQL
sql注入报错之注入原理实例解析
Jun 10 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
Search File Contents PHP 搜索目录文本内容的代码
2010/02/21 PHP
基于PHP常用函数的用法详解
2013/05/10 PHP
php 如何获取文件的后缀名
2016/06/05 PHP
Laravel5中防止XSS跨站攻击的方法
2016/10/10 PHP
javascript实现的基于金山词霸网络翻译的代码
2010/01/15 Javascript
Node.js实现简单聊天服务器
2014/06/20 Javascript
js获取会话框prompt的返回值的方法
2015/01/10 Javascript
jQuery实现html元素拖拽
2015/07/21 Javascript
JS实现仿QQ面板的手风琴效果折叠菜单代码
2015/09/11 Javascript
JavaScript如何实现组合列表框中元素移动效果
2016/03/01 Javascript
js中动态创建json,动态为json添加属性、属性值的实例
2016/12/02 Javascript
JS实现css hover操作的方法示例
2017/04/07 Javascript
vue-cli+webpack在生成的项目中使用bootstrap实例代码
2017/05/26 Javascript
web前端vue实现插值文本和输出原始html
2018/01/19 Javascript
使用 vue.js 构建大型单页应用
2018/02/10 Javascript
这15个Vue指令,让你的项目开发爽到爆
2019/10/11 Javascript
JQuery 实现文件下载的常用方法分析
2019/10/29 jQuery
Vue-axios-post数据后端接不到问题解决
2020/01/09 Javascript
Vue Object 的变化侦测实现代码
2020/04/15 Javascript
Python实现子类调用父类的方法
2014/11/10 Python
浅谈Python用QQ邮箱发送邮件时授权码的问题
2018/01/29 Python
Python使用百度翻译开发平台实现英文翻译为中文功能示例
2019/08/08 Python
Pandas数据离散化原理及实例解析
2019/11/16 Python
python运用pygame库实现双人弹球小游戏
2019/11/25 Python
解决python中的幂函数、指数函数问题
2019/11/25 Python
Python中sorted()排序与字母大小写的问题
2020/01/14 Python
python 提高开发效率的5个小技巧
2020/10/19 Python
CSS3教程:background-clip和background-origin
2008/10/17 HTML / CSS
css3实现input输入框颜色渐变发光效果代码
2014/04/02 HTML / CSS
馥蕾诗美国官网:Fresh美国
2019/10/09 全球购物
Java如何格式化日期
2012/08/07 面试题
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的一样吗
2013/05/01 面试题
高三自我鉴定
2013/10/23 职场文书
新闻专业毕业生英文求职信
2014/03/19 职场文书
学位证书委托书
2014/09/30 职场文书
Java中多线程下载图片并压缩能提高效率吗
2021/07/01 Java/Android