+-
MySQL 5.7奇怪的性能降低与ASC / DESC在分区表上的顺序
将 MySQL Server更新到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`;

它因索引(device,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行为是什么原因,我该如何解决?

最佳答案
我不是MySQL开发人员所以我不知道完整的细节.

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

Partitioning: Index condition pushdown did not work with partitioned tables. (Bug #17306882, Bug #70001)

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

optimizer_switch = index_condition_pushdown =关

通过使用SET [GLOBAL] optimizer_switch =’index_condition_pushdown = off’,可以在不重新启动的情况下尝试此操作.

我们还查看了ORDER BY -`utc` ASC方法,但因为它将filesort添加到每个执行计划中而被吓跑了.

点击查看更多相关文章

转载注明原文:MySQL 5.7奇怪的性能降低与ASC / DESC在分区表上的顺序 - 乐贴网