当你在用explain工具查看sql语句的执行计划时,若select_type 字段中出现“DEPENDENT SUBQUERY”时,你要注意了,你已经掉入了mysql子查询慢的“坑"。

相关书籍:高性能MySQL(第3版) 中文PDF带目录清晰版 http://www.linuxidc.com/Linux/2014-10/108464.htm

下面我们来看一个具体的例子

有这样一条查询语句:

SELECT gid,COUNT(id) as count FROM shop_goods g1 WHERE status =0 and gid IN (SELECT gid FROM shop_goods g2 WHERE sid IN  (1519066,1466114,1466110,1466102,1466071,1453929))GROUP BY gid;

用explain看了一下,出现关键字“DEPENDENT SUBQUERY”,意味着子查询的第一个select依赖外部的查询;

SUBQUERY:子查询中的第一个SELECT;DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询 。

换句话说,就是 子查询对 g2 的查询方式依赖于外层 g1 的查询。它意味着两步:

第一步,MySQL 根据 select gid,count(id) from shop_goods where status=0 group by gid; 得到一个大结果集 t1,其数据量为rows=850672 了;

第二步,上面的大结果集 t1 中的每一条记录,都将与子查询 SQL 组成新的查询语句:select gid from shop_goods where sid in (15...blabla..29) and gid=%t1.gid%。等于说,子查询要执行85万次……即使这两步查询都用到了索引,但不慢才怪;

如此一来,子查询的执行效率居然受制于外层查询的记录数,那还不如拆成两个独立查询顺序执行呢。

对于此类语句一般的优化策略是拆成两个查询语句,你不想拆成两个独立查询的话,也可以与临时表join查询,:

你不想拆成两个独立查询的话,也可以与临时表联表查询,如下所示优化后的sql:

SELECT g1.gid,count(1) FROM shop_goods g1,(select gid from shop_goods WHERE sid in (1519066,1466114,1466110,1466102,1466071,1453929)) g2 where g1.status=0 and g1.gid=g2.gid GROUP BY g1.gid;

用explain看了一下,这次又有了一个新的关键字"DERIVED",意思是用于 from 子句里有子查询的情况。MySQL 会递归执行这些子查询,把结果放在临时表里,然后再做join操作;

DERIVED 的官方含义为:用于 from 子句里有子查询的情况。MySQL 会递归执行这些子查询,把结果放在临时表里。

《高性能MySQL》的第4.4节“MySQL查询优化器的限制(Limitations of the MySQL Query Optimizer)”之第4.4.1小节“关联子查询(Correlated Subqueries)”也有类似的论述:mysql 在处理子查询时,会改写子查询。通常情况下,我们希望由内到外,先完成子查询的结果,然后再用子查询来驱动外查询的表,完成查询。

例如:select * from test where tid in(select fk_tid from sub_test where gid=10);通常我们会感性地认为该 sql 的执行顺序是:sub_test 表中根据 gid 取得 fk_tid(2,3,4,5,6)记录,然后再到 test 中,带入 tid=2,3,4,5,6,取得查询数据。

但是实际mysql的处理方式为:

select * from test where exists (select * from sub_test where gid=10 and sub_test.fk_tid=test.tid);

mysql 将会扫描 test 中所有数据,每条数据都将会传到子查询中与 sub_test 关联,子查询不会先被执行,所以如果 test 表很大的话,那么性能上将会出现问题。

MySQL子查询慢现象的解决的更多相关文章

  1. 第09章 MySQL子查询

    第09章 MySQL子查询 子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL 4.1开始引入. SQL 中子查询的使用大大增强了 SELECT 查询的能力,因为很多时候查询需要 ...

  2. [慢查优化]慎用MySQL子查询,尤其是看到DEPENDENT SUBQUERY标记时

    案例梳理时间:2013-9-25 写在前面的话: 在慢查优化1和2里都反复强调过 explain 的重要性,但有时候肉眼看不出 explain 结果如何指导优化,这时候还需要有一些其他基础知识的佐助, ...

  3. Mysql子查询、关联查询

    mysql中update.delete.install尽量不要使用子查询 一.mysql查询的五种子句         where(条件查询).having(筛选).group by(分组).orde ...

  4. Mysql子查询IN中使用LIMIT

    学习下Mysql子查询IN中使用LIMIT的方法. 这两天项目里出了一个问题,mysql LIMIT使用后报错. 需求是这样的,我有3张表,infor信息表,mconfig物料配置表,maaply物料 ...

  5. MySQL 子查询 EXISTS 和 NOT EXISTS(转)

    MySQL EXISTS 和 NOT EXISTS 子查询 MySQL EXISTS 和 NOT EXISTS 子查询语法如下: SELECT ... FROM table WHERE EXISTS ...

  6. mysql子查询慢的问题

      当你在用explain工具查看sql语句的运行计划时.若select_type 字段中出现"DEPENDENT SUBQUERY"时,你要注意了.你已经掉入了mysql子查询慢 ...

  7. MySQL子查询,派生表和通用表达式

    一:子查询 1.介绍 在另一个查询(外部查询)中嵌套另一个查询语句(内部查询),并使用内部查询的结果值作为外部查询条件. 2.子查询在where中 SELECT customerNumber, che ...

  8. MySQL子查询有哪五种形式?

    MySQL是一个关系型数据库管理系统,由瑞典MySQLAB公司开发,目前属于Oracle旗下产品.MySQL是最流行的关系型数据库管理系统之一,在web应用方面,MySQL是最好的RDBMS(Rela ...

  9. mysql子查询用法

    mysql子查询用法 1 可以当值来用<pre>select id from hcyuyin_share where id=(select id from hcyuyin_share li ...

随机推荐

  1. 使用phpstorm+wamp实现php代码实时调试审计

    转载自:https://www.bugbank.cn/q/article/5853afaffc0bf4f010ee6ac3.html php调试有N多好用的工具,最近研究到phpstorm配合wamp ...

  2. USB枚举过程【转】

    转自:http://blog.csdn.net/myarrow/article/details/8270029 1. 枚举是什么?        枚举就是从设备读取一些信息,知道设备是什么样的设备,如 ...

  3. 关于 VS 2010 和 VS 2013 的警告 LNK4042

    由于我最近调整了一下 Jimi 的文件结构,导致出现了一个 LNK4042 的 warning,我并没有很重视,这个 warning 导致出现了一些错误. 我调试了几个小时,一开始并没有想到是这个 w ...

  4. 数组的splice方法

    splice 该方法向或者从数组中添加或者删除项目,返回被删除的项目,同时也会改变原数组. splice(index,howmany,item1,...itemX) index参数:必须,整数,规定添 ...

  5. C#, CLR, and .NET Framework versions

  6. PHP科学计数法转换成数字

    /** * 科学计数法转换成数字 * @param $num * @param int $double * @return int */ function sctonum($num, $double ...

  7. 【BZOJ2059】Buying Feed 购买饲料

    题面 约翰开车来到镇上,他要带V吨饲料回家.如果他的车上有X吨饲料,每公里就要花费X^2元,开车D公里就需要D* X^2元.约翰可以从N家商店购买饲料,所有商店都在一个坐标轴上,第i家店的位置是Xi, ...

  8. 在win7_64bit + ubuntu-12.04-desktop-amd64+VMware-workstation-full-10.0.1-1379776平台上安装ns-allinone-2.35

    step1.  ns-allinone-2.35的下载地址:http://www.isi.edu/nsnam/ns/ns-build.html#allinone step2.  在虚拟机中打开term ...

  9. Linux系统运维笔记(二),Linux文件编辑命令

    Linux系统运维笔记 Linux文件编辑命令 首先我们使用命令 vi filename 打开一个文件,这个时候进入到的是命令模式 接下来我们按i,然后键盘随便输入写内容. 然后按ESC重新进入到命令 ...

  10. THUSC 2018 酱油记

    THUSC 2018 酱油记 游记分类:游记 Day \((-inf,-2]\) 自CTSC和APIO挂烂以后,仍然在停课集训,不过好像这两波考试让我的RP涨了一大波,因此模拟赛大多都考的不错,虽然经 ...