Skip to content

Workaround для MariaDB

Разбор задачи, где нужно было реализовать логику, обычно решаемую через оконные функции, в условиях ограничений версии MariaDB, где ROW_NUMBER() ещё не поддерживался.

Задача

Построить статистический отчёт по максимальному количеству:

  • одновременных конференций;
  • одновременных пользователей;
  • значений с разбивкой по дням и без нее.

Источник данных - события входа и выхода участников конференций из Openfire.

Контекст

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

В современной SQL-СУБД такую задачу удобно решать через оконные функции вроде ROW_NUMBER() и последующие вычисления поверх упорядоченного набора строк.

Проблема была в том, что используемая версия MariaDB таких функций еще не поддерживала. При этом:

  • обновление БД не входило в задачу;
  • менять внешнюю систему хранения было нежелательно;
  • отчет нужно было реализовать в существующей инфраструктуре.

Ограничение

Нельзя было опереться на стандартный современный подход с оконными функциями.

Это означало, что нужно было вручную воспроизвести две ключевые возможности:

  • устойчивую нумерацию строк в нужном порядке;
  • последующий расчет максимума по уже упорядоченной последовательности событий.

Решение

Вместо ROW_NUMBER() была сделана схема с временными таблицами.

Сначала формировалась промежуточная таблица с датами входа и выхода. Затем создавалась временная таблица ord_tmp, куда события старта интервалов записывались с AUTO_INCREMENT полем start_ordinal. По сути это и было заменой ROW_NUMBER() для стартовых событий.

Дальше:

  • в таблицу отдельно загружались события начала интервала;
  • затем туда же добавлялись события конца интервала;
  • после этого данные перекладывались в финальную временную таблицу уже в детерминированном порядке: по времени события, типу события и внутреннему порядковому номеру.

На выходе получалась последовательность, над которой уже можно было считать максимум одновременных активных интервалов без оконных функций.

Ключевая идея алгоритма

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

Дальше максимум считался формулой:

MAX(2 * start_ordinal - start_or_end_ordinal)

Это позволяло получить максимальное количество одновременно активных интервалов:

  • для конференций;
  • для пользователей;
  • как за весь период, так и по дням.

Фактически удалось вручную воспроизвести поведение, которое в более новых версиях SQL обычно решается оконной аналитикой.

Почему это было хорошим решением

Решение дало практический результат без рискованных инфраструктурных изменений:

  • без обновления версии MariaDB;
  • без переписывания хранилища;
  • без выноса расчета в отдельный сервис;
  • с повторным использованием одной и той же схемы для нескольких отчетов.

Отдельно ценно то, что логика была вынесена в общий базовый слой отчетов, а не размножена вручную по разным запросам.

Результат

В продукте появился рабочий механизм расчета максимального количества одновременных конференций и пользователей в условиях старой MariaDB, где оконные функции были недоступны.

Это позволило:

  • реализовать нужные статистические отчеты в текущем стеке;
  • не блокироваться на ограничениях версии БД;
  • сохранить решение полностью внутри существующей системы.

См. также

Сайт обновлен и проверен: