https://blog.csdn.net/gua___gua/article/details/47401621

MySQL in查询优化<一>

原创 2015年08月10日 17:57:56
  • 5137

开发说他写了个SQL特别慢,让看看。

  1. select * from t_channel where id_ in(select distinct cdbh from sjkk_gcjl where jgsj>'2015-01-02 08:00:00' and jgsj<'2015-01-02 12:00:00');
  2. ......
  3. 30min+

然后我查询内部SQL,只需要3s+

  1. mysql> select distinct cdbh from sjkk_gcjl where jgsj>'2015-01-02 08:00:00' and jgsj<'2015-01-02 12:00:00';
  2. .....
  3. 1755 rows in set (3.30 sec)
  4. mysql> select count(*) from t_channel;
  5. ....
  6. 12062 rows in set (0.70 sec)

开发写的SQL为啥那么慢呢?看看执行计划

  1. explain extended select * from t_channel where id_ in(select distinct cdbh from sjkk_gcjl where jgsj>'2015-01-02 08:00:00' and jgsj<'2015-01-02 12:00:00');
  2. +----+--------------------+-----------+-------+---------------+----------+---------+------+--------+----------+------------------------------+
  3. | id | select_type        | table     | type  | possible_keys | key      | key_len | ref  | rows   | filtered | Extra                        |
  4. +----+--------------------+-----------+-------+---------------+----------+---------+------+--------+----------+------------------------------+
  5. |  1 | PRIMARY            | t_channel | ALL   | NULL          | NULL     | NULL    | NULL |  12062 |   100.00 | Using where                  |
  6. |  2 | DEPENDENT SUBQUERY | sjkk_gcjl | range | idx_jgsj      | idx_jgsj | 8       | NULL | 731868 |   100.00 | Using where; Using temporary |
  7. +----+--------------------+-----------+-------+---------------+----------+---------+------+--------+----------+------------------------------

看看数据库转换后的语句

  1. mysql> show warnings;
  2. SELECT
  3. `shanghai_full`.`t_channel`.`ID_` AS `ID_`,
  4. `shanghai_full`.`t_channel`.`Code_` AS `Code_`,
  5. ...... --这里会列出所有字段
  6. FROM
  7. `shanghai_full`.`t_channel`
  8. WHERE
  9. < in_optimizer > (
  10. `shanghai_full`.`t_channel`.`ID_` ,< EXISTS > (
  11. SELECT DISTINCT
  12. 1
  13. FROM
  14. `shanghai_full`.`sjkk_gcjl`
  15. WHERE
  16. (
  17. (
  18. `shanghai_full`.`sjkk_gcjl`.`jgsj` > '2015-01-02 08:00:00'
  19. )
  20. AND (
  21. `shanghai_full`.`sjkk_gcjl`.`jgsj` < '2015-01-02 12:00:00'
  22. )
  23. AND (
  24. < CACHE > (
  25. `shanghai_full`.`t_channel`.`ID_`
  26. ) = `shanghai_full`.`sjkk_gcjl`.`cdbh`
  27. )
  28. )
  29. )
  30. );

可见,经过mysql优化器后,in 给转换成exists的方式(mysql认为换成exists更快,呵呵)。

慢的原因:走了exists,查询把外表t_channel做为主表进行全表扫描,每扫描一行数据,然后对子查询进行查询看这条数据是否符合条件。

特别说明:mysql版本是5.5。在5.6中mysql做了改进,将in的这种查询转换为了join。

优化方式一(将in查询转换为连接查询)

  1. select t1.* from t_channel t1,(select distinct cdbh from sjkk_gcjl where jgsj>'2015-01-02 08:00:00' and jgsj<'2015-01-02 12:00:00') t2 where t1.id_=t2.cdbh;
  2. ......
  3. 1264 rows in set (3.30 sec)
  4. mysql> explain extended select t1.* from t_channel t1,(select distinct cdbh from sjkk_gcjl where jgsj>'2015-01-02 08:00:00' and jgsj<'2015-01-02 12:00:00') t2 where t1.id_www.255055.cn/ =t2.cdbh;
  5. +----+-------------+------------+--------+---------------+----------+---------+---------+--------+----------+------------------------------+
  6. | id | select_type | table      | type   | possible_keys | key      | key_len | ref     | rows   | filtered | Extra                        |
  7. +----+-------------+------------+--------+---------------+----------+---------+---------+--------+----------+------------------------------+
  8. |  1 | PRIMARY     | <derived2> | ALL    | NULL          | NULL     | NULL    | NULL    |   1755 |   100.00 |                              |
  9. |  1 | PRIMARY     | t1    www.boshenyl.cn      | eq_ref | PRIMARY,ID_   | PRIMARY  | 74      | t2.cdbh |      1 |   100.00 | Using where                  |
  10. |  2 | DERIVED     | sjkk_gcjl  | range  | idx_jgsj      | idx_jgsj | 8       | NULL    | 731868 |   100.00 | Using where; Using temporary |
  11. +----+-------------+------------+--------+---------------+----------+---------+---------+--------+----------+------------------------------+
  12. mysql> show warnings;
  13. SELECT
  14. `shanghai_full`.`t1`.`ID_` AS `ID_`,
  15. ........ ---这里会列出所有字段FROM
  16. `shanghai_full`.`t_channel` `t1`
  17. JOIN (
  18. SELECT DISTINCT
  19. `shanghai_full`.`sjkk_gcjl`.`cdbh` AS `www.cnzhaotai.com cdbh`
  20. FROM
  21. `shanghai_full`.www.fengshen157.com `sjkk_gcjl`
  22. WHERE
  23. (
  24. (
  25. `shanghai_full`.`sjkk_gcjl`.`jgsj` > '2015-01-02 08:00:00'
  26. )
  27. AND (
  28. `shanghai_full`.`sjkk_gcjl`.`jgsj` < '2015-01-02 12:00:00'
  29. )
  30. )
  31. ) `t2`
  32. WHERE
  33. (
  34. `shanghai_full`.`t1`.`ID_` = www.taohuayuan178.com `t2`.`cdbh`
  35. );

优化方式二(使用memory引擎的临时表)

  1. mysql> create temporary table tmp_www.yibaoyule1.com channel  engine=memory (select distinct cdbh from sjkk_gcjl where jgsj>'2015-01-02 08:00:00' and jgsj<'2015-01-02 12:00:00');
  2. Query OK, 1755 rows affected (9.00 sec)
  3. Records: 1755  Duplicates: 0  Warnings: 0
  4. mysql> select * from t_channel where id_ in(select * from tmp_channel);
  5. .....
  6. 1264 rows in set (0.26 sec)
  7. mysql> explain extended select * from t_channel where id_ in(select * from tmp_channel);
  8. +----+--------------------+-------------+------+---------------+------+---------+------+------+----------+-------------+
  9. | id | select_type        | table       | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
  10. +----+--------------------+-------------+------+---------------+------+---------+------+------+----------+-------------+
  11. |  1 | PRIMARY            | t_channel   | ALL  | NULL          | NULL | NULL    | NULL | 3224 |   100.00 | Using where |
  12. |  2 | DEPENDENT SUBQUERY | tmp_channel | ALL  | NULL          | NULL | NULL    | NULL |   20 |   100.00 | Using where |
  13. +----+--------------------+-------------+------+---------------+------+---------+------+------+----------+-------------+
  14. mysql> show warnings;
  15. | Note  | 1003 | select `vmc_jiaqi`.`t_channel`.`ID_` AS `ID_`,`vmc_jiaqi`.`t_channel`.`Code_` AS `Code_`,`vmc_jiaqi`.`t_channel`.`HostId_` AS `HostId_`,`vmc_jiaqi`.`t_channel`.`RoadMonitorStationId_` AS `RoadMonitorStationId_`,`vmc_jiaqi`.`t_channel`.`ChannelNo_` AS `ChannelNo_`,`vmc_jiaqi`.`t_channel`.`Name_` AS `Name_`,`vmc_jiaqi`.`t_channel`.`ChannelType_` AS `ChannelType_`,`vmc_jiaqi`.`t_channel`.`Ext_` AS `Ext_`,`vmc_jiaqi`.`t_channel`.`DeviceAddress_` AS `DeviceAddress_`,`vmc_jiaqi`.`t_channel`.`MinSpeed_`www.mhylpt.comS `MinSpeed_`,`vmc_jiaqi`.`t_channel`.`MaxSpeed_` AS `MaxSpeed_`,`vmc_jiaqi`.`t_channel`.`LimitMinRatio_` AS `LimitMinRatio_`,`vmc_jiaqi`.`t_channel`.`LimitMaxRatio_` AS `LimitMaxRatio_`,`vmc_jiaqi`.`t_channel`.`Direction_` AS `Direction_`,`vmc_jiaqi`.`t_channel`.`JcDirection_` AS `JcDirection_`,`vmc_jiaqi`.`t_channel`.`LaneNum_` AS `LaneNum_`,`vmc_jiaqi`.`t_channel`.`FrameDropNum_` AS `FrameDropNum_`,`vmc_jiaqi`.`t_channel`.`RecogizeRectLeft_` AS `RecogizeRectLeft_`,`vmc_jiaqi`.`t_channel`.`RecogizeRectTop_` AS `RecogizeRectTop_`,`vmc_jiaqi`.`t_channel`.`RecogizeRectWidth_` AS `RecogizeRectWidth_`,`vmc_jiaqi`.`t_channel`.`RecogizeRectHeight_` AS `RecogizeRectHeight_`,`vmc_jiaqi`.`t_channel`.`RmpServerIp_` AS `RmpServerIp_`,`vmc_jiaqi`.`t_channel`.`RmpServerPort_` AS `RmpServerPort_`,`vmc_jiaqi`.`t_channel`.`VirtualGateServerId_` AS `VirtualGateServerId_`,`vmc_jiaqi`.`t_channel`.`LaneType_` AS `LaneType_`,`vmc_jiaqi`.`t_channel`.`DeviceType_` AS `DeviceType_`,`vmc_jiaqi`.`t_channel`.`ManufacturerId_` AS `ManufacturerId_`,`vmc_jiaqi`.`t_channel`.`IsLocalSavePicture_` AS `IsLocalSavePicture_`,`vmc_jiaqi`.`t_channel`.`OrderNO_` AS `OrderNO_`,`vmc_jiaqi`.`t_channel`.`channelStatus` AS `channelStatus` from `vmc_jiaqi`.`t_channel` where <in_optimizer>(`vmc_jiaqi`.`t_channel`.`ID_`,<exists>(select 1 from `vmc_jiaqi`.`tmp_channel` where (<cache>(`vmc_jiaqi`.`t_channel`.`ID_`) = `vmc_jiaqi`.`tmp_channel`.`cdbh`)))

注意:第二种方式还是使用了exists的执行方式,所以这种方式没有第一种方式好,在特定的条件下可能会有用处,

MySQL in查询优化的更多相关文章

  1. php mysql 一个查询优化的简单例子

    PHP+Mysql是一个最经常使用的黄金搭档,它们俩配合使用,能够发挥出最佳性能,当然,如果配合Apache使用,就更加Perfect了. 因此,需要做好对mysql的查询优化.下面通过一个简单的例子 ...

  2. WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)

    WebAPI调用笔记   前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...

  3. 查询优化 | MySQL慢查询优化

    ​Explain查询:rows,定位性能瓶颈. 只需要一行数据时,使用LIMIT1. 在搜索字段上建立索引. 使用ENUM而非VARCHAR. 选择区分度高的列作为索引. 采用扩展索引,而不是新建索引 ...

  4. MySQL 慢查询优化

    为什么查询速度会慢 1.慢是指一个查询的响应时间长.一个查询的过程: 客户端发送一条查询给服务器 服务器端先检查查询缓存,如果命中了缓存,则立可返回存储在缓存中的结果.否则进入下一个阶段 服务器端进行 ...

  5. MySQL SQL查询优化技巧详解

    MySQL SQL查询优化技巧详解 本文总结了30个mysql千万级大数据SQL查询优化技巧,特别适合大数据里的MYSQL使用. 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 ...

  6. 关于mysql的查询优化

    由于工作原因,最近甲方客户那边多次反应了他们那边的系统查询速度慢,经过排除之后,发现他们那边的数据库完全没有用到索引,简直坑得一笔,通过慢查询日志分析,为数据表建立了适当的索引之后,查询速度明显的提高 ...

  7. 《MySQL慢查询优化》之SQL语句及索引优化

    1.慢查询优化方式 服务器硬件升级优化 Mysql服务器软件优化 数据库表结构优化 SQL语句及索引优化 本文重点关注于SQL语句及索引优化,关于其他优化方式以及索引原理等,请关注本人<MySQ ...

  8. MySQL 的查询优化

    说起 MySQL 的查询优化,相信大家收藏了一堆奇技淫巧:不能使用 SELECT *.不使用 NULL 字段.合理创建索引.为字段选择合适的数据类型..... 你是否真的理解这些优化技巧?是否理解它背 ...

  9. MySQL慢查询优化

    MySQL数据库是常见的两个瓶颈是CPU和I/O的瓶颈,CPU在饱和的时候一般发生在大量数据进行比对或聚合时.磁盘I/O瓶颈发生在装入数据远大于内存容量的时候,如果应用分布在网络上,那么查询量相当大的 ...

随机推荐

  1. 2017年PHP程序员未来路在何方?(转载)

    PHP 从诞生到现在已经有 20 多年历史,从 Web 时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js . GO . Python 不断地在挑战 PHP 的地位.这些 ...

  2. Lavavel5.5源代码 - 限流工具

    app('redis')->connection('default')->throttle('key000') // 每60秒,只能有10个资源被获取,在3秒内获取不到锁抛出异常 -> ...

  3. win10在此处打开命令cmd

    Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directory\shell\OpenCmdHere] @="在此处打开命令 ...

  4. itop-4412开发板学习-内核信号量

    1. 翻翻书看下,linux提供两种信号量,内核信号量,由内核控制路径使用,System V IPC信号量,由用户态进程使用.下面的就是内核部分的信号量.内核信号量类似于自旋锁,当锁关闭着时,不允许内 ...

  5. http报文和浏览器缓存机制

    目录 1. 请求报文 1.1请求行 1.2 请求头 一些常用的请求头信息 2. 响应报文 2.1 状态行 1> 响应状态码 2> 常见的响应状态码 2.2 响应头 3. 浏览器缓存 3.1 ...

  6. 【IIS】 常见问题

    [IIS] 常见问题 1. IIS 安装 .Net FrameWork 4.0 开始->所有程序->附件->鼠标右键点击“命令提示符”->以管理员身份运行->%windi ...

  7. 【紫书】(UVa1347)Tour

    继续考虑dp题目. 题意分析 其实这里只是更加仔细的做一个lrj的复读机(Orz 他分析了一个很重要的结果:如果是一个人从左到右再回来,并且每个点恰经过一次,那么等价于两个人从左到右每个点经过一次地遍 ...

  8. Ubuntu下使用Git_4

    在这个第四个文章中,我将练习GIT的高级阶段了,由于高级阶段的内容转的比较多,我自己的代码除了我自己可以看懂意外,大家可能看不懂,所以我将会按照 http://git.wiki.navisec.it/ ...

  9. Ubuntu下使用Git_3

    这里是我举得小白阶段比较困难的地方了, 当在我们向远程数据库推送数据之前,有其他用户向远程数据库推送的相同的文件的时候,服务器会拒绝我们的推送,这个时候就需要我们来整合这两个文件 如图说是,现在显示的 ...

  10. TestNG执行测试用例的顺序

    import org.openqa.selenium.By;import org.openqa.selenium.WebDriver;import org.openqa.selenium.WebEle ...