У меня есть следующая таблица MYSQL:
measuredata:
- ID (bigint)
- timestamp
- entityid
- value (double)
Таблица содержит> 1 миллиард записей. Я хочу иметь возможность визуализировать любое временное окно. Временное окно может быть размером от одного дня до многих лет. В БД примерно каждую минуту измеряются значения.
Таким образом, количество записей для временного окна может быть совершенно другим. Скажем, от нескольких сотен до нескольких тысяч или миллионов.
Эти значения должны отображаться в графической диаграмме-диаграмме на веб-странице.
Если диаграмма - скажем, - шириной 800px, нет смысла получать тысячи строк из базы данных, если временное окно достаточно большое. Я не могу показать более 800 значений на этом графике в любом случае.
Итак, есть ли способ уменьшить набор результатов непосредственно на стороне DB? Я знаю "среднее" и "сумма" и т. Д. c. как агрегатная функция. Но как я могу агрегировать 100 тыс. Строк из большого временного окна, чтобы, скажем, 800 последних строк?
Просто получить эти 100 тыс. Строк и позволить диаграмме выполнить волхвы c не является предпочтительным вариантом. Размер переноса - одна из причин, по которой это невозможно.
Нет ли на стороне БД чего-либо, что я могу использовать? Что-то вроде avg () для сокращения X строк до Y усредненных строк? Или просто волшебный c, чтобы просто пропустить каждую #-ю строку, чтобы уменьшить X до Y?
обновление: хотя я сейчас использую MySQL, я не привязан к этому. Если PostgreSQL fi предоставляет функцию, которая может решить проблему, я готов сменить БД.
update2: возможно, я нашел возможное решение: https://mike.depalatis.net/blog/postgres-time-series-database.html См. Раздел «Агрегация данных».
Ключ не в том, чтобы использовать метку unixtime, а дату и « trun c "it, отредактируйте значения и сгруппируйте их по дате редактирования trun c. Может работать для меня, но потребует переделки моей структуры таблицы. Хм ... может быть, еще кое-что ... все еще исследую ...
update3: Вдохновленный обновлением 2, я пришел с этим запросом:
SELECT (`timestamp` - (`timestamp` % 86400)) as aggtimestamp, `entity`, `value` FROM `measuredata` WHERE `entity` = 38 AND timestamp > UNIX_TIMESTAMP('2019-01-25') group by aggtimestamp
Работает, но моя БД / Кажется, что индекс / структура не очень оптимизированы для этого: запрос за прошлый год занял ~ 75 с c (медленный тестовый компьютер), но в итоге получил только одно значение в день. Это может быть объединено с avg (value
), но это еще больше увеличивает время запроса ... (~ 82se c). Я посмотрю, можно ли еще оптимизировать это. Но теперь у меня есть идея, как работает «понижающая выборка» данных, особенно с агрегацией в сочетании с «группированием по».