参考:http://codingstandards.iteye.com/blog/1344833

上面参考文章中《高性能MySQL》第四章第四节在第三版中我对应章节是第六章第五节

最近分析生产环境慢查询,发现上线很久但是效率不高的查询

MySQL版本5.5.18

SELECT
loc.cell_no AS m_cellNo
...
FROM bs_loc loc LEFT JOIN st_stock_m m ON loc.cell_no = m.cell_no
WHERE
      loc.zone_no = 'B12'
AND loc.WMS_PICKING_FLAG = 'cp'
AND m.cell_no in (SELECT cell_no FROM st_stock_m WHERE goods_no IN (''))

因为开发对这块的逻辑也不是很清楚,不分析逻辑上是否可以直接goods_no拿出来直接约束结果集,单纯从in子查询无法使用到索引来看MySQL优化器是如何去处理的

SELECT 
    `ma`.`loc`.`CELL_NO` AS `m_cellNo`
    FROM `ma`.`bs_loc` `loc` JOIN `ma`.`st_stock_m` `m`
    WHERE
      ((`ma`.`loc`.`ZONE_NO` ='B33') AND<in_optimizer>(`ma`.`m`.`CELL_NO`,
      <EXISTS>
        (SELECT1FROM `ma`.`st_stock_m` WHERE ((`ma`.`st_stock_m`.`GOODS_NO` ='') AND (<CACHE>(`ma`.`m`.`CELL_NO`) = `ma`.`st_stock_m`.`CELL_NO`))))
        AND (`ma`.`loc`.`CELL_NO` = `ma`.`m`.`CELL_NO`))

执行计划

其实子查询返回的结果集最多不会超过3个,通常我们认为内部会按照使用结果集逐一去查,效率会很快,但实际上不是

以为内部的操作会是

步骤1:
SELECT group_concat(cell_no) FROM st_stock_m WHERE goods_no IN ('') into @cell_no;
步骤2
SELECT
loc.cell_no AS m_cellNo
... FROM bs_loc loc LEFT JOIN st_stock_m m ON loc.cell_no = m.cell_no
WHERE
      loc.zone_no = 'B12'
AND loc.WMS_PICKING_FLAG = 'cp'
AND m.cell_no in (@cell_no);

按照《高性能MySQL》中所说:

把这个查询拿到MariaDB测试了一下,确实要比MySQL 5.5.18处理效果好很多。

SELECT 
    `ma`.`loc`.`CELL_NO` AS `m_cellNo`
    FROM `ma`.`bs_loc` `loc` semi JOIN (`ma`.`st_stock_m`) JOIN `ma`.`st_stock_m` `m`
    WHERE
      (
        (`ma`.`m`.`CELL_NO` = `ma`.`st_stock_m`.`CELL_NO`) AND
        (`ma`.`loc`.`ZONE_NO` ='B33') AND
        (`ma`.`st_stock_m`.`GOODS_NO` ='') AND
        (`ma`.`loc`.`CELL_NO` = `ma`.`st_stock_m`.`CELL_NO`)
      )

执行计划

MariaDB优化器改写后使用的semi join,这块MariaDB官网有部分说明:

https://mariadb.com/kb/en/mariadb/semi-join-materialization-strategy/

《MySQL技术内幕:SQL编程》中对于MariaDB优化器对于子查询和join的优化部分有说明

其他博文对于MySQL5.5以及MariaDB5.3优化器对比的文章:

http://blog.sina.com.cn/s/blog_aa8dc60801012pzc.html

http://www.server110.com/mariadb/201310/2245.html

【MySQL】MySQL/MariaDB的优化器对in子查询的处理的更多相关文章

  1. MYSQL优化派生表(子查询)在From语句中的

    Mysql 在5.6.3中,优化器更有效率地处理派生表(在from语句中的子查询): 优化器推迟物化子查询在from语句中的子查询,知道子查询的内容在查询正真执行需要时,才开始物化.这一举措提高了性能 ...

  2. 【mysql的设计与优化专题(5)】慢查询详解

    查询mysql的操作信息 show status -- 显示全部mysql操作信息 show status like "com_insert%"; -- 获得mysql的插入次数; ...

  3. mysql常用基础操作语法(十)~~子查询【命令行模式】

    mysql中虽然有连接查询实现多表连接查询,但是连接查询的性能很差,因此便出现了子查询. 1.理论上,子查询可以出现在查询语句的任何位置,但实际应用中多出现在from后和where后.出现在from后 ...

  4. MySQL数据库(12)----ALL、ANY、SOME子查询

    运算符 ALL 和 ANY 常与某个关系比较运算符结合在一起使用,以便测试列子查询的结果.它们会测试比较值与子查询返回的全部或部分值是否匹配.例如,当比较值小于或等于子查询返回的每个值时,<= ...

  5. MySQL 5.7 跟踪优化器

    Welcome to the MySQL monitor.  Commands end with ; or \g.Your MySQL connection id is 5Server version ...

  6. 【MYSQL】update/delete/select语句中的子查询

    update或delete语句里含有子查询时,子查询里的表不能在update或是delete语句中,如含有运行时会报错:但select语句里含有子查询时,子查询里的表可以在select语句中. 如:把 ...

  7. MySQL与MariaDB核心特性比较详细版v1.0(覆盖mysql 8.0/mariadb 10.3,包括优化、功能及维护)

    注:本文严禁任何形式的转载,原文使用word编写,为了大家阅读方便,提供pdf版下载. MySQL与MariaDB主要特性比较详细版v1.0(不含HA).pdf 链接:https://pan.baid ...

  8. 深入理解MySql子查询IN的执行和优化

    IN为什么慢? 在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕.例如: SELECT driver_id FROM driver where driver_id in (SELECT dr ...

  9. MySQL · 特性分析 · 优化器 MRR & BKA【转】

    MySQL · 特性分析 · 优化器 MRR & BKA 上一篇文章咱们对 ICP 进行了一次全面的分析,本篇文章小编继续为大家分析优化器的另外两个选项: MRR & batched_ ...

随机推荐

  1. [CSS]去除inline-block元素间距的几种方法

    当我们使用inline-block 时,会出现空白间距问题. 但这些间距对我们的布局,或兼容性产生影响,我们需要去除它,该怎么办?下面简单介绍几种方法: 1.去掉html元素之间的空格,直接写在一行. ...

  2. HDU 5428 The Factor

    话说这题意真的是好难懂啊,尽管搜到了中文题意,然而还是没懂,最后看到了一个题解才懂的.http://www.cnblogs.com/Apro/p/4784808.html#3470972 题意:给出n ...

  3. CF 461B Appleman and Tree 树形DP

    Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other ...

  4. JDK动态代理与Cglib库

    JDK动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在 ...

  5. TNT平台

    1, TNT平台 本词条缺少信息栏.名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! TNT平台中的开发平台是基于微软Jupiter平台的快速开发工具,开发者可以通过界面属性设定的方法来 ...

  6. JAVA 根据用户输入数据求某年到某年有多少天

    实例: import java.util.*; //求某年到某年有多少天 public class Test{ public static void main(String[] args){ Scan ...

  7. laravel项目return back()->withErrors($validator)或return back()->with('errors','原密码错误!')在前台原密码错误的情况下不能正确显示错误信息,变成报错!

    被折磨的答案是 php artisan --version看一下版本,如果是5.2.26以上的,在路由处删除web中间件分组,还有问题再反馈

  8. Java Cookie和Session(转载)

    一.cookie机制和session机制的区别 具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案. 同时我们也看到,由于才服务器端保持状态的 ...

  9. 聚合查询中的Group by

    2005版本以上的sql server 查询中如果既包含聚合函数列(诸如sum ,count,avg,max等)又存在一般列的情况,则查询字符串结尾必须包含Group By [某一般列].  其实微软 ...

  10. 和为S的两个数字VS和为s的连续正数序列

    题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s.如果有多对数字的和等于s,输出任意一对即可. 例如输入数组1.2.4.7.11.15和数字15.由于4+11=15, ...