高效的MySQL分页
来源:asp之家 发布时间:2011-01-04 20:01:00
PERCONA PERFORMANCE CONFERENCE 2009上,来自雅虎的几位工程师带来了一篇”Efficient Pagination Using MySQL“的报告,有很多亮点,本文是在原文基础上的进一步延伸。
首先看一下分页的基本原理:
mysql> explain SELECT * FROM message ORDER BY id DESC LIMIT 10000, 20\G
***************** 1. row **************
id: 1
select_type: SIMPLE
table: message
type: index
possible_keys: NULL
key: PRIMARY
key_len: 4
ref: NULL
rows: 10020
Extra:
1 row in set (0.00 sec)
limit 10000,20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行,问题就在这里,如果是limit 100000,100,需要扫描100100行,在一个高并发的应用里,每次查询需要扫描超过10W行,性能肯定大打折扣。文中还提到limit n性能是没问题的,因为只扫描n行。
文中提到一种”clue”的做法,给翻页提供一些”线索”,比如还是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页20条,当前是第10页,当前页条目id最大的是9527,最小的是9500,如果我们只提供”上一页”、”下一页”这样的跳转(不提供到第N页的跳转),那么在处理”上一页”的时候SQL语句可以是:
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20;
处理”下一页”的时候SQL语句可以是:
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 20;
不管翻多少页,每次查询只扫描20行。
缺点是只能提供”上一页”、”下一页”的链接形式,但是我们的产品经理非常喜欢”<上一页 1 2 3 4 5 6 7 8 9 下一页>”这样的链接方式,怎么办呢?
如果LIMIT m,n不可避免的话,要优化效率,只有尽可能的让m小一下,我们扩展前面的”clue”做法,还是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页20条,当前是第10页,当前页条目id最大的是9527,最小的是9500,比如要跳到第8页,我看的SQL语句可以这样写:
SELECT * FROM message WHERE id > 9527 ORDER BY id ASC LIMIT 20,20;
跳转到第13页:
SELECT * FROM message WHERE id < 9500 ORDER BY id DESC LIMIT 40,20;
原理还是一样,记录住当前页id的最大值和最小值,计算跳转页面和当前页相对偏移,由于页面相近,这个偏移量不会很大,这样的话m值相对较小,大大减少扫描的行数。其实传统的limit m,n,相对的偏移一直是第一页,这样的话越翻到后面,效率越差,而上面给出的方法就没有这样的问题。
注意SQL语句里面的ASC和DESC,如果是ASC取出来的结果,显示的时候记得倒置一下。
已在60W数据总量的表中测试,效果非常明显。


猜你喜欢
- Python命令启动Web服务器实例详解利用Python自带的包可以建立简单的web服务器。在DOS里cd到准备做服务器根目录的路径下,输入
- 加载相关库import randomimport seaborn as snsimport matplotlib.pyplot as plt
- 前提条件:本地已经安装好oracle单实例,能使用plsql developer连接,或者能使用TNS连接串远程连接到oracle集群读取e
- JavaScript Date.toDateString()方法返回一个Date对象的人类可读形式的日期部分。语法Date.to
- 从容器、可迭代对象谈起所有的容器都是可迭代的(iterable),迭代器提供了一个next方法。iter()返回一个迭代器,通过next()
- python类私有属性和公共属性对于python而言,类的属性的可见度只有两种,public和private。类的私有属性便是在前面加上&a
- 目标打包Python selenium 自动化脚本(如下run.py文件)为exe执行文件,使之可以直接在未安装python环境的windo
- 最近的一些疫情信息很让人揪心,为了方便大家掌握疫情信息,在空闲之余做了一个关于 nCoV 的疫情监控小助手。主要的功能是通过企业微信的 We
- 1.迭代器当您创建一个列表时,你可以逐个读取它的项。逐项读取其项称为迭代:mylist是一个可迭代的对象。当你使用列表解析式时,你创建了一个
- 1. 张量的拼接(1) numpy.concatenatenp.concatenate((a1,a2,a3,…), axis=0)张量的拼接
- 安装SQL Server2019详细教程1、官网下载SQL Server 2019 Developer: Developer下载地址&nbs
- goods表如下:name time productA 2016-1-2 13:23:
- 简介由于项目在注册、登录、找回密码 时需要发送短信验证的功能,我们使用腾讯云短信做。为什么要用腾讯云短信呢? 因为注册就送 100条免费短信
- 一个懒加载的树状表格实例实现一个树状表格,需要用到vxe-table这个库,虽然element-ui也能实现,但这个库是专门针对表格做了更多
- 一、安装ROS-OpenCV安装OpenCVsudo apt-get install ros-kinetic-vision-opencv l
- XML(可扩展标记语言)已成为Web应用中数据表示和数据交换的标准,随着Internet的快速发展,尤其是电子商务,Web服务等应用的广泛使
- 本文实例讲述了GO语言实现简单TCP服务的方法。分享给大家供大家参考。具体实现方法如下:package mainimport ("
- element-ui界面非常简洁和美观,提供的组件可以满足绝大多数的应用场景,当表格中显示了图片的缩略图时,想要鼠标浮动在缩略图上时放大图片
- 在使用SQL Server 的过程,中由于经常需要从多个不同地点将数据集中起来或向多个地点复制数据,所以数据的导出,导入是极为常见的操作.我
- 改变列的数据类型 [sql] ALTER TABLE visitor MODIFY nam VARCHAR(30); 追加新列 [sql]