Я видел вопрос, на который почти ответили по ряду потоков, но не учитывая последствия для этого конкретного домена:
Я ищу для хранения данных временных рядов в MySQL для большого количества датчиков (500 и растет), каждый из которых обеспечивает одно значение с плавающей точкой с 5-минутными интервалами.В простейшем случае структура будет выглядеть так: - gauge_id - timestamp - значение
(где gauge_id и timestamp объединяются в качестве первичного ключа)
Это означает примерно 105120 строк на датчик в год - все, что необходимохраниться в течение 10 или 20 лет.Тогда для 1000 датчиков мы будем рассматривать 100 миллионов записей в год.
Данные записываются в пакетах, обычно значения для каждого канала объединяются в файл XML из удаленного источника и считываются в базу данных каждый час.или ежедневно.Таким образом, самое большее, количество вставок в час равно количеству датчиков.
Операции чтения данных будут выполняться для каждого датчика (поэтому операции объединения данных между датчиками не будут) в зависимости от временного диапазона.Так, например, чтобы получить все значения для датчика X между двумя датами.Обычно это также включает в себя некоторую форму функции агрегации / интерполяции - поэтому пользователь может захотеть увидеть среднесуточные значения или максимальные значения за неделю и т. Д. Для произвольных диапазонов.Опять же, сравнительно небольшое количество операций чтения, но для этого требуется ответ менее чем за 1 секунду от MySQL.
На этом этапе я склоняюсь к 1 таблице на один датчик, а не делаю одну огромную таблицу в MySQL на gauge_id.Логика заключается в том, что это облегчит разбиение в дальнейшем, упростит резервное копирование и, по существу, облегчит удаление / восстановление датчиков, если на любом этапе возникнут ошибки в данных.Затраты на операции записи и чтения немного сложнее.
Есть мысли по этому поводу?
-------- ОБНОВЛЕНИЕ --------
Я провел несколько тестов на своем MacBook 2,4 ГГц Core 2 Duo, 4 ГБ ОЗУ.
Настройте следующую таблицу:
CREATE TABLE `test` (
`channel_id` int(10) NOT NULL,
`time` datetime NOT NULL,
`value` int(10) NOT NULL,
KEY `channel_id` (`channel_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Заполнено с помощью хранимой процедуры:
CREATE PROCEDURE `addTestData`(IN ID INT, IN RECORDS INT)
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE j DATETIME DEFAULT '1970-01-01 00:00:00';
WHILE (i<=RECORDS) DO
INSERT INTO test VALUES(ID,j,999);
SET i=i+1;
SET j= j + INTERVAL 15 MINUTE;
END WHILE;
END $$
пока я звонил, чтобы создать первые 1 миллион записей
call addTestData(1,1000000);
вставка, выполненная за 47 секунд
SELECT * FROM `test` WHERE channel_id = 1 and YEAR(time) = '1970';
, выполненная за 0,0006 секунд
SELECT AVG(value) as value, DATE(time) as date FROM `test`
WHERE channel_id = 1 and YEAR(time) = '1970' group by date;
выполняется за 4,6 с (функции MAX, SUM выполняются одновременно).
после добавления еще 4-х датчиков:
call addTestData(2,1000000);
call addTestData(3,1000000);
call addTestData(4,1000000);
call addTestData(5,1000000);
вставка выполняется за 47 с, 78мегабайты, использованные для таблицы
Я выполнил те же два запроса - и получил точно такое же время выполнения, что и 1 миллион записей в таблице (4,6 секунды для более крупного запроса).
Итак,исключить потенциальное использование для шардинга, резервного копирования и будущих изменений на аппаратном уровне в таблице любого отдельного датчика (т. е. несколько показаний, изменениеинтервал данных), как представляется, нет необходимости разбивать на несколько таблиц для обозримого.Даже не пытался запустить запрос с разделами, похоже, не было никаких причин.
-------- ОДНАКО -------------
Поскольку 4,6 секунды для запроса не являются идеальными, нам, очевидно, необходимо провести некоторую оптимизацию.В качестве первого шага я реструктурировал запрос:
SELECT
AVG(value) as value,
DATE(time) as date
FROM
(SELECT * FROM test
WHERE channel_id = 1 and YEAR(time) = '1970')
as temp
group by date;
Выполнение таблицы с 5 миллионами записей (более 5 идентификаторов канала): запрос занимает 4,3 секунды.Если я запускаю его на столе с 1 каналом, 1 миллионом записей, он запускается за 0,36 секунды !!Немного почесывая голову над этим ...
Секционирование таблицы из 5 миллионов записей
ALTER TABLE test PARTITION BY HASH(channel_id) PARTITIONS 5;
Впоследствии завершается сложный запрос, описанный выше, также через 0,35 секунды, что приводит к аналогичному увеличению производительности.