优化Mysql查询左连接

优化Mysql查询左连接,mysql,performance,left-join,query-optimization,explain,Mysql,Performance,Left Join,Query Optimization,Explain,我们希望通过以下查询将校准数据的条目映射到校准数据。但在我看来,这个查询的持续时间太长了(>24小时) 是否有可能进行优化? 我们现在根据需要增加了测试更多索引的功能,但这对持续时间没有任何影响 [编辑] 硬件不应该是最大的瓶颈 128 GB内存 1TB SSD RAID 5 32芯 解释结果 +----+-------------+-------+------------+------+---------------+------+---------+------+---------+--

我们希望通过以下查询将校准数据的条目映射到校准数据。但在我看来,这个查询的持续时间太长了(>24小时)

是否有可能进行优化? 我们现在根据需要增加了测试更多索引的功能,但这对持续时间没有任何影响

[编辑]

硬件不应该是最大的瓶颈

  • 128 GB内存
  • 1TB SSD RAID 5
  • 32芯
解释结果

+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra                                          |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+------------------------------------------------+
|  1 | SIMPLE      | cal   | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2009 |   100.00 | Using temporary; Using filesort                |
|  1 | SIMPLE      | m     | NULL       | ALL  | visit         | NULL | NULL    | NULL | 3082466 |   100.00 | Range checked for each record (index map: 0x1) |
+----+-------------+-------+------------+------+---------------+------+---------+------+---------+----------+------------------------------------------------+
需要太长时间的查询:

Insert into knn_data (SELECT cal.X           AS X, 
        cal.Y           AS Y, 
        cal.BeginTime   AS BeginTime, 
        cal.EndTime     AS EndTime, 
        avg(m.dbm_ant)  AS avg_dbm_ant, 
        m.ant_id        AS ant_id, 
        avg(m.location) avg_location, 
        count(*)        AS count, 
        m.visit 
 FROM   calibration cal 
        LEFT join calibration_data m
          ON m.visit BETWEEN cal.BeginTime AND cal.EndTime 
 GROUP  BY cal.X, 
           cal.Y, 
           cal.BeginTime, 
           cal. BeaconId, 
           m.ant_id,
           m.macHash,
           m.visit; 
表knn_数据:

    CREATE TABLE `knn_data` (
  `X` int(11) NOT NULL,
  `Y` int(11) NOT NULL,
  `BeginTime` datetime NOT NULL,
  `EndTIme` datetime NOT NULL,
  `avg_dbm_ant` float DEFAULT NULL,
  `ant_id` int(11) NOT NULL,
  `avg_location` float DEFAULT NULL,
  `count` int(11) DEFAULT NULL,
  `visit` datetime NOT NULL,
  PRIMARY KEY (`ant_id`,`visit`,`X`,`Y`,`BeginTime`,`EndTIme`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
表校准

BeaconId, X, Y, BeginTime, EndTime
41791, 1698, 3944, 2016-11-12 22:44:00, 2016-11-12 22:49:00


CREATE TABLE `calibration` (
  `BeaconId` int(11) DEFAULT NULL,
  `X` int(11) DEFAULT NULL,
  `Y` int(11) DEFAULT NULL,
  `BeginTime` datetime DEFAULT NULL,
  `EndTime` datetime DEFAULT NULL,
  KEY `x,y` (`X`,`Y`),
  KEY `x` (`X`),
  KEY `y` (`Y`),
  KEY `BID` (`BeaconId`),
  KEY `beginTime` (`BeginTime`),
  KEY `x,y,beg,bid` (`X`,`Y`,`BeginTime`,`BeaconId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
表1校准数据

macHash, visit, dbm_ant, ant_id, mac, isRand, posX, posY, sources, ip, dayOfMonth, location, am, ar
'f5:dc:7d:73:2d:e9', '2016-11-12 22:44:00', '-87', '381', 'f5:dc:7d:73:2d:e9', NULL, NULL, NULL, NULL, NULL, '12', '18.077636300207715', 'inradius_41791', NULL


CREATE TABLE `calibration_data` (
  `macHash` varchar(100) COLLATE utf8_bin NOT NULL,
  `visit` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `dbm_ant` int(3) NOT NULL,
  `ant_id` int(11) NOT NULL,
  `mac` char(17) COLLATE utf8_bin DEFAULT NULL,
  `isRand` tinyint(4) DEFAULT NULL,
  `posX` double DEFAULT NULL,
  `posY` double DEFAULT NULL,
  `sources` int(2) DEFAULT NULL,
  `ip` int(10) unsigned DEFAULT NULL,
  `dayOfMonth` int(11) DEFAULT NULL,
  `location` varchar(80) COLLATE utf8_bin DEFAULT NULL,
  `am` varchar(300) COLLATE utf8_bin DEFAULT NULL,
  `ar` varchar(300) COLLATE utf8_bin DEFAULT NULL,
  KEY `visit` (`visit`),
  KEY `macHash` (`macHash`),
  KEY `ant, time` (`dbm_ant`,`visit`),
  KEY `beacon` (`am`),
  KEY `ant_id` (`ant_id`),
  KEY `ant,mH,visit` (`ant_id`,`macHash`,`visit`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

在“范围”查询中,这是一个令人讨厌的经典问题:优化者不使用索引,最终会进行完整的表扫描。在您的解释计划中,您可以在列
type=ALL
上看到这一点

理想情况下,您应该在键列中包含
type=range
和一些内容

一些想法:


我怀疑把你从

ON m.visit BETWEEN cal.BeginTime AND cal.EndTime 



这就是我所想的……

在“范围”查询中,这是一个令人讨厌的经典问题:优化者不使用您的索引,最终会进行完整的表扫描。在您的解释计划中,您可以在列
type=ALL
上看到这一点

理想情况下,您应该在键列中包含
type=range
和一些内容

一些想法:


我怀疑把你从

ON m.visit BETWEEN cal.BeginTime AND cal.EndTime 



这就是我想做的一切…

一次性任务?那没关系吧?加载此数据后,是否每天递增更新“汇总表”

收缩数据类型——庞大的数据需要更长的处理时间。示例:4字节的
INT
DayOfMonth
可以是1字节的
TINYINT无符号的

您正在将
时间戳
移动到
日期时间
。这可能会也可能不会像您预期的那样起作用

INT UNSIGNED
适用于IPv4,但不能将IPv6安装在其中

COUNT(*)
可能不需要4字节的
INT
;请参阅较小的变体

在适当的情况下使用未签名的

一个mac地址需要19个字节;它可以很容易地转换成6字节的二进制(6)
。请参见
REPLACE()
UNHEX()
HEX()

innodb缓冲池大小的设置是什么?对于你的大公羊来说可能是100克左右

时间范围重叠吗?如果没有,那就好好利用。另外,不要在
主键中包含不必要的列,例如
EndTime

按与knn_数据的主键相同的顺序排列
GROUP BY
列;这将避免在
插入过程中出现大量块拆分

最大的问题是,
calibration\u data
中没有有用的索引,因此,
JOIN
必须一次又一次地进行全表扫描!一个扩展的2K扫描3M行!让我把重点放在这个问题上

因为MySQL不知道日期时间范围是否重叠,所以在开始和结束之间没有很好的方法。在这种情况下没有真正的治疗方法,所以让我换一种方式来处理它


开始和结束是“常规”的吗?像每小时一样?当然,我们可以做一些计算,而不是在
之间进行
。如果是这样,请告诉我;我会继续我的想法。

一次性任务?那没关系吧?加载此数据后,是否每天递增更新“汇总表”

收缩数据类型——庞大的数据需要更长的处理时间。示例:4字节的
INT
DayOfMonth
可以是1字节的
TINYINT无符号的

您正在将
时间戳
移动到
日期时间
。这可能会也可能不会像您预期的那样起作用

INT UNSIGNED
适用于IPv4,但不能将IPv6安装在其中

COUNT(*)
可能不需要4字节的
INT
;请参阅较小的变体

在适当的情况下使用未签名的

一个mac地址需要19个字节;它可以很容易地转换成6字节的二进制(6)
。请参见
REPLACE()
UNHEX()
HEX()

innodb缓冲池大小的设置是什么?对于你的大公羊来说可能是100克左右

时间范围重叠吗?如果没有,那就好好利用。另外,不要在
主键中包含不必要的列,例如
EndTime

按与knn_数据的主键相同的顺序排列
GROUP BY
列;这将避免在
插入过程中出现大量块拆分

最大的问题是,
calibration\u data
中没有有用的索引,因此,
JOIN
必须一次又一次地进行全表扫描!一个扩展的2K扫描3M行!让我把重点放在这个问题上

因为MySQL不知道日期时间范围是否重叠,所以在开始和结束之间没有很好的方法。在这种情况下没有真正的治疗方法,所以让我换一种方式来处理它


开始和结束是“常规”的吗?像每小时一样?当然,我们可以做一些计算,而不是在
之间进行
。如果是这样,请告诉我;我会继续我的想法。

谢谢!!使用on和where条件尝试您的解决方案!解释显示了11.11的过滤值,因此值得测试。
之间的
=
等相同。注意一个潜在的错误:两个公式都包含在内,因此边界处的项目可能包含在两个不同的桶中!对
上的
设置为否。由于限制较少,它将扫描额外的行。@RickJames目的是让它使用索引而不是扫描更少的行。。。谢谢你的回答自从这个答案被接受以来,它真的有帮助吗?很多
Insert into knn_data (SELECT cal.X           AS X, 
        cal.Y           AS Y, 
        cal.BeginTime   AS BeginTime, 
        cal.EndTime     AS EndTime, 
        avg(m.dbm_ant)  AS avg_dbm_ant, 
        m.ant_id        AS ant_id, 
        avg(m.location) avg_location, 
        count(*)        AS count, 
        m.visit 
 FROM   calibration cal 
        LEFT join calibration_data m
          ON m.visit >= cal.BeginTime 
 WHERE m.visit <= cal.EndTime 
 GROUP  BY cal.X, 
           cal.Y, 
           cal.BeginTime, 
           cal. BeaconId, 
           m.ant_id,
           m.macHash,
           m.visit;