Learning Platform
Глоссарий Troubleshooting
Урок 14.06 · 30 мин
Продвинутый
time seriesWITH FILLtoStartOfIntervalgroupArrayMovingSumgap fillingneighborrolling aggregate

Time-Series: паттерны аналитических запросов

Module 07 покрывал schema design для time-series: порядок столбцов в ORDER BY, codec chains (Delta+ZSTD, Gorilla+LZ4), PARTITION BY для lifecycle management. Здесь — паттерны запросов: как правильно агрегировать по временным интервалам, заполнять пропуски, вычислять скользящие метрики.


toStartOfInterval: bucketing по фиксированным интервалам

Группировка временных событий по фиксированным интервалам — базовый паттерн time-series аналитики.

-- Агрегация по часам
SELECT
    toStartOfHour(ts)    AS hour,
    count()              AS events,
    avg(response_ms)     AS avg_latency
FROM http_requests
WHERE ts >= now() - INTERVAL 7 DAY
GROUP BY hour
ORDER BY hour;

Семейство функций toStartOf*:

ФункцияШагТипичное применение
toStartOfMinute(ts)1 минReal-time дашборды
toStartOfFiveMinutes(ts)5 минSLA-мониторинг
toStartOfHour(ts)1 часПочасовые тренды
toStartOfDay(ts)1 деньДневная статистика
toStartOfInterval(ts, INTERVAL 15 MINUTE)ПроизвольныйНестандартные интервалы

Функция toStartOfInterval наиболее гибкая — принимает произвольный интервал:

-- 15-минутные bucket'ы
SELECT
    toStartOfInterval(ts, INTERVAL 15 MINUTE) AS bucket,
    count()                                    AS requests
FROM http_requests
GROUP BY bucket
ORDER BY bucket;

WITH FILL: заполнение пропусков в временных рядах

Если в некоторые интервалы не было событий, GROUP BY пропустит их. Для дашбордов и графиков нужны непрерывные ряды с нулями на пустых интервалах.

Time-Series паттерны запросов
Bucketing (toStartOfInterval)Bucketing (toStartOfInterval) -- группировка событий по фиксированным временным интервалам. Без gap-filling: пустые интервалы пропускаются. Применение: любая агрегация по времени.
Gap-filling (WITH FILL)Gap-filling (WITH FILL) -- заполнение пустых интервалов в ORDER BY. FROM/TO/STEP определяют диапазон и шаг генерации. Пустые строки получают NULL, которые можно заменить на 0 через coalesce().
Rolling (groupArrayMovingSum)Rolling aggregates (groupArrayMovingSum/Avg) -- скользящие суммы и средние за N предыдущих периодов. Применение: 7-дневная скользящая сумма revenue, 30-дневный MA для сглаживания выбросов.

Синтаксис WITH FILL:

-- Полный пример: почасовые события за 7 дней с gap-filling
SELECT
    toStartOfHour(ts)  AS hour,
    count()            AS events
FROM user_events
WHERE ts >= now() - INTERVAL 7 DAY
GROUP BY hour
ORDER BY hour
WITH FILL
    FROM toStartOfHour(now() - INTERVAL 7 DAY)
    TO   toStartOfHour(now())
    STEP INTERVAL 1 HOUR;

WITH FILL гарантирует, что в результате будут все часовые интервалы от FROM до TO с шагом STEP — даже если в эти часы не было событий. Для пустых интервалов значения агрегатных функций будут NULL (для дашбордов их заменяют через coalesce(events, 0)).

WARNING

WITH FILL работает только в ORDER BY. Секция FROM ... TO ... STEP ... необязательна, но без неё диапазон определяется по фактическим данным — пустые интервалы в начале и конце не генерируются. Всегда указывайте явный диапазон FROM/TO для предсказуемых результатов.


groupArrayMovingSum: скользящие суммы

groupArrayMovingSum(N) вычисляет скользящую сумму за N предыдущих значений. Применяется после агрегации по временному интервалу.

-- 7-дневная скользящая сумма revenue
SELECT
    day,
    daily_revenue,
    groupArrayMovingSum(7)(daily_revenue) AS rolling_7d
FROM (
    SELECT
        toStartOfDay(ts)    AS day,
        sum(revenue)        AS daily_revenue
    FROM orders
    GROUP BY day
    ORDER BY day
)
ORDER BY day;

Функции семейства:

ФункцияОписаниеПрименение
groupArrayMovingSum(N)(col)Скользящая сумма за N периодовRolling revenue, накопленные события
groupArrayMovingAvg(N)(col)Скользящее среднее за N периодовСглаживание метрик, MA-индикаторы
WARNING

groupArrayMovingSum(N) работает на массиве значений в рамках одной GROUP BY группы. Для корректного результата необходимо явно сортировать по времени (ORDER BY day) перед применением функции — иначе порядок элементов массива будет недетерминированным.


neighbor и runningDifference: дельта-ряды

Для вычисления разницы между соседними точками времени используйте neighbor() или runningDifference().

-- Дельта между соседними значениями (прирост за период)
SELECT
    ts,
    value,
    value - neighbor(value, -1) AS delta
FROM metrics
WHERE metric_name = 'requests_total'
ORDER BY ts;
-- runningDifference: накопленный счётчик -> скорость
SELECT
    ts,
    runningDifference(requests_total) AS requests_per_interval
FROM (
    SELECT
        toStartOfMinute(ts) AS ts,
        max(requests_total) AS requests_total
    FROM counters
    GROUP BY ts
    ORDER BY ts
);

neighbor(col, offset) — обращается к значению col в строке на offset позиций выше (отрицательный) или ниже (положительный) в текущем блоке. runningDifference(col) эквивалентно col - neighbor(col, -1) с нулём для первой строки.


Lifecycle: PARTITION BY + TTL

Для time-series данных с ограниченным горизонтом хранения используйте PARTITION BY по временному ключу в сочетании с TTL-правилами. Подробно см. Module 10 (TTL и Tiered Storage).

-- Оперативные метрики: 90 дней на SSD, 1 год на объектном хранилище
CREATE TABLE metrics_hot (
    ts          DateTime64(3) CODEC(Delta, ZSTD(1)),
    metric_name LowCardinality(String),
    value       Float64 CODEC(Gorilla, LZ4)
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(ts)
ORDER BY (metric_name, ts)
TTL ts + INTERVAL 90 DAY TO VOLUME 'cold';

Ключевые выводы

  1. toStartOfInterval(ts, INTERVAL N UNIT) — универсальная функция bucketing, принимающая произвольный интервал. Семейство toStartOfHour/Day/Week — короткие алиасы.
  2. WITH FILL FROM ... TO ... STEP INTERVAL ... в ORDER BY заполняет пустые временные интервалы для непрерывных рядов. Без явного FROM/TO пустые интервалы на краях не генерируются.
  3. groupArrayMovingSum(N) и groupArrayMovingAvg(N) вычисляют скользящие агрегаты. Требуют предварительной сортировки по времени.
  4. neighbor(col, -1) и runningDifference(col) — для delta-вычислений между соседними точками ряда.
  5. TTL + PARTITION BY toYYYYMM(ts) — стандартный lifecycle паттерн для time-series (детально в Module 10).
Window functions: LAG, LEAD и вычисление дельт между строками Spark time windowing: tumbling, sliding и session windows

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 3. Дашборд показывает почасовые события за последние 7 дней. В некоторые ночные часы не было событий, и график показывает пропуски вместо нулей. Какой SQL-конструкт заполнит пропуски для непрерывного ряда?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 8