MySQL in查詢優化
阿新 • • 發佈:2018-04-21
-name tails join spa csdn duplicate 查詢 tracking 全表掃描
[html] view plain copy
https://blog.csdn.net/gua___gua/article/details/47401621
MySQL in查詢優化<一>
原創 2015年08月10日 17:57:56開發說他寫了個SQL特別慢,讓看看。
[html] view plain copy- 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‘);
- ......
- 30min+
然後我查詢內部SQL,只需要3s+
[html] view plain copy
- mysql> select distinct cdbh from sjkk_gcjl where jgsj>‘2015-01-02 08:00:00‘ and jgsj<‘2015-01-02 12:00:00‘;
- .....
- 1755 rows in set (3.30 sec)
- mysql> select count(*) from t_channel;
- ....
- 12062 rows in set (0.70 sec)
[html] view plain copy
- 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‘);
- +----+--------------------+-----------+-------+---------------+----------+---------+------+--------+----------+------------------------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
- +----+--------------------+-----------+-------+---------------+----------+---------+------+--------+----------+------------------------------+
- | 1 | PRIMARY | t_channel | ALL | NULL | NULL | NULL | NULL | 12062 | 100.00 | Using where |
- | 2 | DEPENDENT SUBQUERY | sjkk_gcjl | range | idx_jgsj | idx_jgsj | 8 | NULL | 731868 | 100.00 | Using where; Using temporary |
- +----+--------------------+-----------+-------+---------------+----------+---------+------+--------+----------+------------------------------
[html] view plain copy
- mysql> show warnings;
- SELECT
- `shanghai_full`.`t_channel`.`ID_` AS `ID_`,
- `shanghai_full`.`t_channel`.`Code_` AS `Code_`,
- ...... --這裏會列出所有字段
- FROM
- `shanghai_full`.`t_channel`
- WHERE
- < in_optimizer > (
- `shanghai_full`.`t_channel`.`ID_` ,< EXISTS > (
- SELECT DISTINCT
- 1
- FROM
- `shanghai_full`.`sjkk_gcjl`
- WHERE
- (
- (
- `shanghai_full`.`sjkk_gcjl`.`jgsj` > ‘2015-01-02 08:00:00‘
- )
- AND (
- `shanghai_full`.`sjkk_gcjl`.`jgsj` < ‘2015-01-02 12:00:00‘
- )
- AND (
- < CACHE > (
- `shanghai_full`.`t_channel`.`ID_`
- ) = `shanghai_full`.`sjkk_gcjl`.`cdbh`
- )
- )
- )
- );
可見,經過mysql優化器後,in 給轉換成exists的方式(mysql認為換成exists更快,呵呵)。
慢的原因:走了exists,查詢把外表t_channel做為主表進行全表掃描,每掃描一行數據,然後對子查詢進行查詢看這條數據是否符合條件。
特別說明:mysql版本是5.5。在5.6中mysql做了改進,將in的這種查詢轉換為了join。
優化方式一(將in查詢轉換為連接查詢)
[html] view plain copy
- 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;
- ......
- 1264 rows in set (3.30 sec)
- 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;
- +----+-------------+------------+--------+---------------+----------+---------+---------+--------+----------+------------------------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
- +----+-------------+------------+--------+---------------+----------+---------+---------+--------+----------+------------------------------+
- | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 1755 | 100.00 | |
- | 1 | PRIMARY | t1 www.boshenyl.cn | eq_ref | PRIMARY,ID_ | PRIMARY | 74 | t2.cdbh | 1 | 100.00 | Using where |
- | 2 | DERIVED | sjkk_gcjl | range | idx_jgsj | idx_jgsj | 8 | NULL | 731868 | 100.00 | Using where; Using temporary |
- +----+-------------+------------+--------+---------------+----------+---------+---------+--------+----------+------------------------------+
- mysql> show warnings;
- SELECT
- `shanghai_full`.`t1`.`ID_` AS `ID_`,
- ........ ---這裏會列出所有字段FROM
- `shanghai_full`.`t_channel` `t1`
- JOIN (
- SELECT DISTINCT
- `shanghai_full`.`sjkk_gcjl`.`cdbh` AS `www.cnzhaotai.com cdbh`
- FROM
- `shanghai_full`.www.fengshen157.com `sjkk_gcjl`
- WHERE
- (
- (
- `shanghai_full`.`sjkk_gcjl`.`jgsj` > ‘2015-01-02 08:00:00‘
- )
- AND (
- `shanghai_full`.`sjkk_gcjl`.`jgsj` < ‘2015-01-02 12:00:00‘
- )
- )
- ) `t2`
- WHERE
- (
- `shanghai_full`.`t1`.`ID_` = www.taohuayuan178.com `t2`.`cdbh`
- );
優化方式二(使用memory引擎的臨時表)
[html] view plain copy
- 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‘);
- Query OK, 1755 rows affected (9.00 sec)
- Records: 1755 Duplicates: 0 Warnings: 0
- mysql> select * from t_channel where id_ in(select * from tmp_channel);
- .....
- 1264 rows in set (0.26 sec)
- mysql> explain extended select * from t_channel where id_ in(select * from tmp_channel);
- +----+--------------------+-------------+------+---------------+------+---------+------+------+----------+-------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
- +----+--------------------+-------------+------+---------------+------+---------+------+------+----------+-------------+
- | 1 | PRIMARY | t_channel | ALL | NULL | NULL | NULL | NULL | 3224 | 100.00 | Using where |
- | 2 | DEPENDENT SUBQUERY | tmp_channel | ALL | NULL | NULL | NULL | NULL | 20 | 100.00 | Using where |
- +----+--------------------+-------------+------+---------------+------+---------+------+------+----------+-------------+
- mysql> show warnings;
- | 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`)))
MySQL in查詢優化