MySQL 5.7奇怪的性能降低与ASC / DESC在分区表上的顺序

时间:2016-08-18 16:53:49

标签: mysql database

将MySQL服务器更新到5.7版(在Ubuntu 16.04 LTS下)时,我遇到了一些奇怪的麻烦。

Preambula :我有一些包含大量记录的表(约2.5亿)。简而言之,这个表具有这样的结构:

CREATE TABLE `device_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `device` int(11) DEFAULT NULL,
  `data` double NOT NULL DEFAULT '0',
  `utc` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`utc`,`id`),
  KEY `id` (`id`),
  KEY `idx_devutc` (`device`,`utc`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (`utc`)
(PARTITION y_min VALUES LESS THAN (1200000000) ENGINE = MyISAM,
 PARTITION y_121 VALUES LESS THAN (1210000000) ENGINE = MyISAM,
 PARTITION y_122 VALUES LESS THAN (1220000000) ENGINE = MyISAM,
...
...
...
 PARTITION y_167 VALUES LESS THAN (1670000000) ENGINE = MyISAM,
 PARTITION y_168 VALUES LESS THAN (1680000000) ENGINE = MyISAM,
 PARTITION y_169 VALUES LESS THAN (1690000000) ENGINE = MyISAM,
 PARTITION y_max VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */

那么,为什么它有这种不寻常的主键(UTC,ID)?字段ID是自动增量,它可以是主键。好吧,我们需要按字段UTC对表进行分区,并且MySQL说要这样做,字段UTC必须是主键或至少是主键的第一部分。我们不能使用UTC作为主键,因为设备每秒可以发送几次数据,所以我们必须使用这样一个奇怪的主键:(UTC,ID)。这没关系。

我们还有(device,utc)对此表进行索引和索引。为什么?因为我们需要执行某些设备在特定时间段内检索数据的查询,例如:

SELECT `utc`, `data` 
FROM `device_data` 
WHERE `device` = :DeviceId AND `utc` >= :UtcFrom AND `utc` < :UtcTo 
ORDER BY `utc`;

由于索引(设备,utc),它非常快。

Ambula :将MySQL服务器升级到版本5.7(从5.0或5.1,我现在不确定)后,一些查询变得非常慢(2-3分钟而不是100-200毫秒) )。一些小调查发现了一个条件:当排序顺序是后代时,查询速度会下降。

此查询仍然很快(100毫秒):

SELECT `utc`, `data` 
FROM `device_data` 
WHERE `device` = :DeviceId AND `utc` >= :UtcFrom AND `utc` < :UtcTo 
ORDER BY `utc` ASC;

但是这个查询非常慢(~180秒):

SELECT `utc`, `data` 
FROM `device_data` 
WHERE `device` = :DeviceId AND `utc` >= :UtcFrom AND `utc` < :UtcTo 
ORDER BY `utc` DESC;

当然,使用相同的参数值。 在以前版本的MySQL Server中,两个查询都很快(100-200毫秒)。

经过两天的努力工作后,我发现了一些避免这个问题的技巧:

SELECT `utc`, `data` 
FROM `device_data` 
WHERE `device` = :DeviceId AND `utc` >= :UtcFrom AND `utc` < :UtcTo 
ORDER BY -`utc` ASC;

(在ORDER BY中的utc之前的减号上加上

此查询也很快,以毫秒结束,并按照相反的顺序返回记录,正如我们所需。

问题:这种奇怪的MySQL行为是什么原因,我该如何解决?

1 个答案:

答案 0 :(得分:4)

我不是MySQL开发者,所以我不知道详细信息。

然而,在battled this on their issue tracker之后,最好的猜测是它是由this fix added in 5.7.3引起的回归:

  

分区:索引条件下推功能不适用于分区表。 (Bug#17306882,Bug#70001)

我们能够通过在my.cnf中设置此问题来规避问题,从而强调了这一理论:

optimizer_switch=index_condition_pushdown=off

可以尝试使用SET [GLOBAL] optimizer_switch='index_condition_pushdown=off'而无需重新启动。

我们还查看了ORDER BY -`utc` ASC方法,但在为每个执行计划添加Using filesort时被吓跑了。