Mysql大范围分页优化案例
在BBS线上业务抓到如下分页SQL:
142597301 meizu_bbs 192.168.17.72:39096 meizu_bbs Query 217 Sending data SELECT * FROM pre_forum_thread WHERE fid=22 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 1933100, 50
142597338 meizu_bbs 192.168.17.72:39128 meizu_bbs Query 216 Sending data SELECT * FROM pre_forum_thread WHERE fid=22 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 1933100, 50
142604367 nagiosuser 127.0.0.1:39893 NULL Query 0 NULL show full processlist
这个SQL一共有3个问题:
1:select * 这种写法不符合SQL编写规范,任何时候都不要用*来代替具体的列名称,需要什么列就取什么列。如果表里有个text/blob等大字段,影响就更加明显。
2:pre_forum_thread 表在tid字段做了分区,但是查询里面没有用到分区字段,这样就需要扫描全部分区,性能比不分区更差。
3:在这个分页SQL里,偏移量高到193万。
LIMIT语法:
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
MYSQL是处理LIMIT语句的方式是:取出全部offset+rowcount,然后丢弃掉前面所有行,只返回row_count行。
在这个案例里,在mysql server端需要查询的行数为1933100+50,217S还未得出结果。
优化方案: 最终需要的只是50行记录,如果先取出这50行记录的主键ID,这样是不是会很快? 执行计划和执行时间:
mysql> explain partitions SELECT tid FROM pre_forum_thread WHERE fid=22 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 1933100, 50;
+----+-------------+------------------+-----------------------------------------------------------------------------------------------------------+-------+-------------------------------------------------------------------------------+--------------+---------+------+---------+------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------+-----------------------------------------------------------------------------------------------------------+-------+-------------------------------------------------------------------------------+--------------+---------+------+---------+------------------------------------------+
| 1 | SIMPLE | pre_forum_thread | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25,p26,p27,p28 | range | displayorder,rate,lastpost,fd,fdd,idx_fid_displayorder_heats,idx_displayorder | displayorder | 4 | NULL | 2673718 | Using where; Using index; Using filesort |
+----+-------------+------------------+-----------------------------------------------------------------------------------------------------------+-------+-------------------------------------------------------------------------------+--------------+---------+------+---------+------------------------------------------+
1 row in set (0.00 sec) mysql> SELECT sql_no_cache tid FROM pre_forum_thread WHERE fid=22 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 1933100, 50;
+--------+
| tid |
+--------+
| 795442 |
.........
| 795387 |
| 795168 |
+--------+
50 rows in set (1.02 sec)
分析一下为什么只取出PK值会很快。 在INNODB索引树里面,每个二级索引的叶子节点都会保存一份PK值,通过二级索引查找数据的过程是:从索引树的根节点开始比较索引值是否和查询值匹配,如果不匹配,根据情况进入左或右分支,再比较,直到在找到符合要求的节点,然后从叶节点里取出PK值,再回表根据主键得到全部数据。如果只是查找主键,那么就少了”然后从叶节点里取出PK值,再回表根据主键得到全部数据“这一部分,而这一部分正是最耗时的。在执行计划里可以看到”Using index“,这就说明优化器使用了”覆盖索引“,只需要扫描索引数据就可以得到最终数据,索引一般情况下比数据要小,往往常驻内存,所以虽然偏移量193万,也能给在1.02秒内返回结果。
得到这50个主键ID值之后,用这50条记录再关联原表查询:
mysql> explain select sql_no_cache * from pre_forum_thread A inner join (SELECT tid FROM pre_forum_thread WHERE fid=22 AND displayorder>=0 ORDER BY lastpost DESC LIMIT 1933100, 50) B on A.tid=B.tid;
+----+-------------+------------------+--------+-------------------------------------------------------------------------------+---------+---------+-------+---------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------+--------+-------------------------------------------------------------------------------+---------+---------+-------+---------+----------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 50 | |
| 1 | PRIMARY | A | eq_ref | PRIMARY | PRIMARY | 4 | B.tid | 1 | |
| 2 | DERIVED | pre_forum_thread | ALL | displayorder,rate,lastpost,fd,fdd,idx_fid_displayorder_heats,idx_displayorder | NULL | NULL | NULL | 3307262 | Using filesort |
+----+-------------+------------------+--------+-------------------------------------------------------------------------------+---------+---------+-------+---------+----------------+
3 rows in set (1.03 sec) #执行时间
50 rows in set (1.06 sec)
处理分页的方法有很多种,在业务层面可以限制翻页的起始位置,不允许直接定位到10000页。在数据库查询方面也有别的方法来处理,根据相应的业务需要寻找最佳的处理方法。 本案例里的 LIMIT 1933100, 50 需要规避。
Mysql大范围分页优化案例的更多相关文章
- mysql 大数据分页优化
一.mysql大数据量使用limit分页,随着页码的增大,查询效率越低下. 1. 直接用limit start, count分页语句, 也是我程序中用的方法: select * from prod ...
- MySQL 百万级分页优化
MySQL 百万级分页优化 http://www.jb51.net/article/31868.htm 一般刚开始学SQL的时候,会这样写 : , ; 但在数据达到百万级的时候,这样写会慢死 : , ...
- mysql大内存高性能优化方案
mysql优化是一个相对来说比较重要的事情了,特别像对mysql读写比较多的网站就显得非常重要了,下面我们来介绍mysql大内存高性能优化方案 8G内存下MySQL的优化 按照下面的设置试试看:key ...
- MySQL大数据分页的优化思路和索引延迟关联
之前上次在部门的分享会上,听了关于MySQL大数据的分页,即怎样使用limit offset,N来进行大数据的分页,现在做一个记录: 首先我们知道,limit offset,N的时候,MySQL的查询 ...
- MySql大表分页(附独门秘技)
问题背景 MySql(InnoDB)中的订单表需要按时间顺序分页查询,且主键不是时间维度递增,订单表在百万以上规模,此时如何高效地实现该需求? 注:本文并非主要讲解如何建立索引,以下的分析均建立在有合 ...
- mysql百万级分页优化
普通分页 数据分页在网页中十分多见,分页一般都是limit start,offset,然后根据页码page计算start , 这种分页在几十万的时候分页效率就会比较低了,MySQL需要从头开始一直往后 ...
- Mysql大数据表优化处理
原文链接: https://segmentfault.com/a/1190000006158186 当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表 ...
- MySQL 百万级分页优化(Mysql千万级快速分页)(转)
http://www.jb51.net/article/31868.htm 以下分享一点我的经验 一般刚开始学SQL的时候,会这样写 复制代码 代码如下: SELECT * FROM table OR ...
- MySQL 百万级分页优化(Mysql千万级快速分页)
以下分享一点我的经验 一般刚开始学SQL的时候,会这样写 : SELECT * FROM table ORDER BY id LIMIT 1000, 10; 但在数据达到百万级的时候,这样写会慢死 : ...
随机推荐
- js版扫雷(可直接运行试玩)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 什么是 kNN 算法?
学习 machine learning 的最低要求是什么? 我发觉要求可以很低,甚至初中程度已经可以. 首先要学习一点 Python 编程,譬如这两本小孩子用的书:[1][2]便可. 数学方面 ...
- C# 字符编码类Encoding
在网络通信中,很多情况下都是将字符信息转成字节序列进行传输.将字符序列转为字节序列的过程称为编码.当这些字节传送到接收方,接收方需要逆向将字节序列转为字符序列.这个过程就是解码. 常见编码有ASCII ...
- clip 属性剪裁绝对定位元素
如果left >= right或者bottom <= top,则元素会被完全裁掉而不可见,即“隐藏”.通过这种方式隐藏的元素是可以被屏幕阅读器等辅助设备识别的,从而提高了页面的可用性. I ...
- linux动态时钟探索
在早期的linux内核版本的时间概念都是由周期时钟提供的.虽然比较有效,但是,对于关注能耗电量的系统上,就不能满足长时间休眠的需求,因为周期系统要求必须在一定的频率下,周期性的处于活动状态.因此,li ...
- 关于如何通过json更改背景图片
今天遇到的问题,突然脑子就不灵光了,平时我们在用jquery更改元素css样式,特别是background的时候,通常用的代码 $("body").css("backgr ...
- New XAMPP security concept:错误解决方法
New XAMPP security concept:错误解决方法 (2014-03-06 16:07:46) 转载▼ 分类: php 在Linux上配置xampp后远程访问域名报错: New X ...
- mac上使用imagealpha命令对图片进行压缩批处理
#! /bin/bash #BASE_DIR="/Users/jiading/Documents/basepng"; #OUTPUT_DIR="/Users/jiadin ...
- 分布式系统(Distributed System)资料
这个资料关于分布式系统资料,作者写的太好了.拿过来以备用 网址:https://github.com/ty4z2008/Qix/blob/master/ds.md 希望转载的朋友,你可以不用联系我.但 ...
- tab切换效果
选项卡是一个神奇的网页效果,不论大小网站,比如B2B像阿里巴巴,慧聪网,还有B2C这个不用说了吧,爱逛网店的童鞋们都知道的,像京东商城,淘宝网,拍拍网,一号店,凡客诚品,等等各种网各种网店,选项卡不仅 ...