今天下午,帮同事重写了一个MySQL SQL语句,该SQL语句涉及两张表,其中一张表是字典表(需返回一个字段),另一张表是业务表(本身就有150个字段,需全部返回),当然,字段的个数是否合理在这里不予评价。平时,返回的数据大概5w左右,系统尚能收到数据。但12月31日那天,数据量大概20w,导致SQL执行时间过长,未能在规定的时间内反馈结果,于是系统直接报错。

一般的思路是用MySQL的分页功能,即直接在原SQL语句后面增加LIMIT子句。但请注意,虽然你看到的反馈结果只是LIMIT后面指定的数量,于是想当然的以为MySQL只是检索了指定数量的数据,然后给予返回。其实,MySQL内部实现的原理是,检索所有符合where条件的记录,然后返回指定数量的记录。从这个角度来看,直接在原SQL语句后面添加LIMIT子句只能说是一种可以实现功能的方案,但未必最优。

具体在本例中,首先我们来看一下150个字段的表的统计信息:

一行大概就占2k,而Innodb默认页的大小为16k,这意味着,一个页中最多可存储8行的数据。随机读的可能性大大增加。而这无疑会对数据库系统的IO造成极大的压力。

优化前

如果采用上述方案,即直接在原SQL语句后面增加LIMIT子句,下面,我们来看看它的执行情况。

首先,直接添加LIMIT子句后的SQL语句如下(已省略a1表的150个字段和a2中的一个字段):

FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) WHERE STATUS<>'' AND settle_date=20151230 limit 50000,10000;

其执行时间如下:

大概执行了32s,绝大部分都花费到Sending data上了。Sending data指的是服务器检索数据,读取数据,并将数据返回给客户端的时间。

关于上述执行结果,有以下几点需要说明:

1. 这是SQL语句多次执行后的结果,这样就可以排除结果缓存的影响,事实上,每次查询的时长都是32s左右。

2. 为什么选用的是limit 50000,10000,而不是0,10000,这个主要是考虑到对于LIMIT子句来说,越到后面,分页的成本越高。基于此,选择了中间值来作为分页的结果。

该语句的执行计划如下:

优化后:

优化的思路:

只对该表的主键进行分页,然后用返回的主键作为子查询的结果,来检索该表其它字段的值。

改写后的SQL语句如下:

FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) where seq_id in (select seq_id from (select seq_id FROM upay_csys_scquery_txn_log_his a1  WHERE STATUS<>'' AND settle_date=20151230 order by 1 limit 50000,10000) as t);

其执行时间如下:

大概3s多,比第一种方案快了差不多10倍,效果显著。

下面来看看其执行计划(explain extended)

总结:

1. 改写后的语句原本如下:

FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) where seq_id in (select seq_id FROM upay_csys_scquery_txn_log_his a1  WHERE STATUS<>'' AND settle_date=20151230 order by 1 limit 50000,10000);

但MySQL报以下错误:

ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

需再增加一个嵌套子查询,

比如这样的语句是不能正确执行的。
select * from table where id in (select id from table limit 12); 但是,只要你再加一层就行。如:
select * from table where id in (select t.id from (select * from table limit 12)as t) 这样就可以绕开limit子查询的问题。
问题解决。

2. 如果想查看MySQL查询优化器等价改写后的SQL语句,可首先通过explain extended得到具体的执行计划,然后通过show warnings查看。

具体在本例中,等价改写后的SQL语句如下:

与设想中的执行顺序一致~

3. 如何查看MySQL语句各步骤的执行时间,可参考:http://www.cnblogs.com/ivictor/p/5085965.html

MySQL的分页优化的更多相关文章

  1. 【MySQL】分页优化

    前段时间由于项目的原因,对一个由于分页而造成性能较差的SQL进行优化,现在将优化过程中学习到关于分页优化的知识跟大家简单分享下. 分页不外乎limit,offset,在这两个关键字中,limit其实不 ...

  2. mysql 查询优化~ 分页优化讲解

    一 简介:今天咱们来聊聊mysql的分页查询二 语法     LIMIT [offset,] rows     offset是第多少条     rows代表多少条之后的行数    性能消耗    se ...

  3. [MySQL] LIMIT 分页优化

    背景:LIMIT 0,20 这种分页方式,随着 offset 值的不断增大,当达到百万级时,一条查询就需要1秒以上,这时可以借助索引条件的查询来优化. SQL:select * from member ...

  4. mysql limit分页优化方法分享

    同样是取10条数据  select * from yanxue8_visit limit 10000,10 和  select * from yanxue8_visit limit 0,10  就不是 ...

  5. MySQL 百万级分页优化

    MySQL 百万级分页优化 http://www.jb51.net/article/31868.htm 一般刚开始学SQL的时候,会这样写 : , ; 但在数据达到百万级的时候,这样写会慢死 : , ...

  6. MySQL分页优化中的“INNER JOIN方式优化分页算法”到底在什么情况下会生效?

    本文出处:http://www.cnblogs.com/wy123/p/7003157.html 最近无意间看到一个MySQL分页优化的测试案例,并没有非常具体地说明测试场景的情况下,给出了一种经典的 ...

  7. Mysql分页优化

    数据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, id 是主键,vtype是tinyint,vtype是索引. ...

  8. mysql分页优化方法

    mysql分页优化方法 今天遇到开发反应分页语句很慢,马上看一下到底是啥的分页语句 原分页语句 SELECT * FROM `tt` LIMIT , 执行这个语句需要6秒+时间 执行计划为全表扫描 在 ...

  9. MySQL 百万级分页优化(Mysql千万级快速分页)(转)

    http://www.jb51.net/article/31868.htm 以下分享一点我的经验 一般刚开始学SQL的时候,会这样写 复制代码 代码如下: SELECT * FROM table OR ...

随机推荐

  1. Torch7学习笔记(二)nn Package

    神经网络Package [目前还属于草稿版,等我整个学习玩以后会重新整理] 模块Module module定义了训练神经网络需要的所有基础方法,并且是可以序列化的抽象类. module有两种状态变量: ...

  2. Master-Slave通用基础框架

    一.设计目的 设计出一个通用的Master-Slave基础框架,然后可以基于这个框架来实现特定的业务需求,比如实现多节点并行计算.分布式处理等. 二.设计理念 基于经典的命令模式,Master和Sla ...

  3. SectionIndexer示例

    This small tutorial will show you how to create a ListView, enable fast scrolling, and create a alph ...

  4. html中的图像动态加载问题

    首先要说明下文档加载完成是什么概念 一个页面http请求访问时,浏览器会将它的html文件内容请求到本地解析,从窗口打开时开始解析这个document,页面初始的html结构和里面的文字等内容加载完成 ...

  5. java类加载相关

    可参考一篇文章:http://www.tuicool.com/articles/QZnENv 下面题输出结果 package com.h3c.itac; public class Dervied ex ...

  6. ratina 视网膜屏幕解决方案大全

    第三方教程 http://www.tuicool.com/articles/JBreIn 知乎 https://www.zhihu.com/question/21653056 强烈推荐!!!最牛逼最专 ...

  7. 多线程导出大规模excel文件

    文章有点水,和前几篇没有太大区别,但是单线程处理大文件导出会非常耗时间,用到多线程才能更加合理的利用资源.大文件也可能会超出excel工作表范围.这里也有相应处理 参考:用DataGridView导入 ...

  8. c#多线程介绍(上)

    转载原文:这里是链接内容 转载原文:这里写链接内容 转载原文:这里写链接内容 (重要事情说三遍) 引言 本文主要从线程的基础用法,CLR线程池当中工作者线程与I/O线程的开发,并行操作PLINQ等多个 ...

  9. Kinect for Windows SDK开发学习相关资源

    Kinect for Windows SDK(K4W)将Kinect的体感操作带到了平常的应用学习中,提供了一种不同于传统的鼠标,键盘及触摸的无接触的交互方式,在某种程度上实现了自然交互界面的理想,即 ...

  10. Linux 查找已安装软件的方法

    1.rpm 注意rpm区分大小写 查询已安装的以mysql开头的包 rpm  -qa mysql* 查询已安装的mysql 包 rpm -qa|grep mysql rpm的方法有时候也所有已安装的包 ...