在日期字段上加入时更新速度问题

时间:2018-06-07 11:46:58

标签: mysql sql database performance join

我有一个表,用于存储MySQL 5.6中称为data_points

的时间序列数据点
CREATE TABLE `data_points` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `time_series_id` int(10) unsigned NOT NULL,
  `logged_at` date NOT NULL,
  `data_value` decimal(20,6) DEFAULT NULL,
  `upload_id` int(10) unsigned NOT NULL,
  `is_latest` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `data_points_time_series_id_index` (`time_series_id`),
  KEY `data_points_logged_at_index` (`logged_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

is_latest标志表示数据点是否是给定logged_at日期的最新数据,并且给定time_series_id。插入新数据点后,我需要保留旧版本,但将is_latest标记设置为0

例如,在2018-01-01上,我为1457.2 time_series_id插入了值123的第一个数据点。 is_latest的默认值为1

稍后我想修改该数据点值(同时由于时间点分析的原因而将现有行保留在原位)。因此,我为2018-01-01 44795.778插入了time_series_id的新数据点,其值为123

我现在需要为旧版本设置is_latest标记为0

我有一个更新查询来执行此操作,但在data_points表中执行约300万行需要大约400毫秒...

UPDATE data_points o
LEFT JOIN data_points o2
  ON o2.time_series_id = o.time_series_id
  AND o2.logged_at = o.logged_at
SET o.is_latest = 0
WHERE o.is_latest = 1
  AND o.time_series_id = 123
  AND o.upload_id < o2.upload_id;

我认为问题出在加入日期时o2.logged_at = o.logged_at上的自我加入。

是否有更有效的方法来定义哪些data_points行应标记为is_latest = 0

2 个答案:

答案 0 :(得分:0)

对于此查询:

UPDATE data_points o LEFT JOIN
       data_points o2
       ON o2.time_series_id = o.time_series_id AND
          o2.logged_at = o.logged_at
    SET o.is_latest = 0
WHERE o.is_latest = 1 AND
      o.time_series_id = 123 AND
      o.upload_id < o2.upload_id;

您需要两个索引:data_points(is_latest, time_series_id)data_points(time_series_id, logged_at, upload_id)。第一个可能已经被现有索引覆盖。

答案 1 :(得分:0)

INDEX(time_series_id, is_latest, o.upload_id)

但是,我想知道。当“最大upload_id”具有相同含义时,为什么有is_latest标志?让我们看看使用is_latest的查询,看看我们是否可以摆脱这个标志。通过摆脱它,这将使查询速度提高100%!