Выбор схемы хранения посекундных данных телеметрии (PostgreSQL/Django/Grafana) [закрыто]

Мое приложение каждую секунду получает пакеты телеметрии от оборудования в операционный центр. Каждый пакет идентифицируется фиксированным идентификатором SID, который определяет структуру данных, включая:

  • SID 1: температура оборудования 1, 2, 3, 4
  • SID 2: напряжение батарей 1, 2, 3

Решение Generic EAV уже реализовано и запущено в производство, но оно генерирует очень большой объем данных.

Переписывание уровня хранилища было бы очень дорогостоящим как при разработке, так и при обслуживании.

В Django я могу отображать последнее значение каждого параметра с точностью до наносекунды без проблем.

Однако в Grafana любая попытка создать историческую панель мониторинга (например, данные о температуре за один месяц) требует огромных ресурсов (процессор/память) для выполнения запросов.

Цели:

  1. Сохраняйте отображение последних значений в Django в режиме реального времени
  2. Позволяет эффективно строить временные ряды за несколько месяцев в Grafana без исчерпания ресурсов

Решение 1 - Универсальный EAV, находящийся в производстве:

  • В одной модели Django каждый параметр хранится в таблице Entity–Attribute–Value:

    # models.py
    class ParameterHK(models.Model):
        id                = models.BigAutoField(primary_key=True, db_index=True)
        date_hk_reception = models.DateTimeField(auto_now_add=True, db_index=True)
        sid               = models.IntegerField(db_index=True)
        equipment         = models.CharField(max_length=500)
        label_parameter   = models.CharField(max_length=500, db_index=True)
        unit              = models.CharField(max_length=500)
        value             = models.IntegerField()
        date_hk_obc       = models.IntegerField()
    
  • По одной строке на параметр в секунду.

  • Отлично работает для запросов Django, но вызывает:

    • огромное количество строк
    • очень большие индексы
    • ресурсоемкие запросы агрегации в Grafana

Решение: 2 широкие таблицы для каждого SID:

  • Создайте отдельную таблицу для каждого SID с одним столбцом на параметр. Пример для SID 1:

    CREATE TABLE hk_sid1 (
      ts            TIMESTAMPTZ NOT NULL,
      equip1_temp   INTEGER,
      equip2_temp   INTEGER,
      equip3_temp   INTEGER,
      equip4_temp   INTEGER
    );
    
  • Прямое считывание каждого столбца временного ряда без сложной фильтрации.

  • Более высокая производительность чтения с помощью Grafana.

  • Недостатки: жесткая схема, требует миграции при изменении протокола и управления несколькими таблицами.

Каков дизайн для посекундного потока данных, хранящегося в течение нескольких месяцев, при сохранении решения 1 в рабочем состоянии из-за высокой стоимости полной перезаписи?

Решение 1 не требует перезаписи, но ограничено в производительности исторических запросов.

Решение 2 обеспечивает более быстрое считывание, но является дорогостоящим в разработке и обслуживании.

Какие альтернативы (секционирование, непрерывные агрегаты, понижающая выборка, политики автоматического хранения и т.д.) ограничивают использование ресурсов при сохранении гибкости?

Вернуться на верх