У меня есть таблица, в которой хранятся точки данных временных рядов в 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
для старой ревизии.
У меня есть запрос на обновление, чтобы выполнить это, но для выполнения требуется ~ 400 мс с ~ 3 миллионами строк в таблице data_points
...
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
?