Перейти к основному содержимому
Перейти к основному содержимому

avgState

Описание

Комбинатор State может быть применён к функции avg для получения промежуточного состояния типа AggregateFunction(avg, T), где T — это указанный тип для среднего значения.

Пример использования

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

Сначала создайте исходную таблицу для данных о трафике веб-сайта:

CREATE TABLE raw_page_views
(
    page_id UInt32,
    page_name String,
    response_time_ms UInt32,  -- Page response time in milliseconds
    viewed_at DateTime DEFAULT now()
)
ENGINE = MergeTree()
ORDER BY (page_id, viewed_at);

Создайте агрегирующую таблицу, которая будет хранить средние времена ответа. Обратите внимание, что avg не может использовать тип SimpleAggregateFunction, так как ему требуется сложное состояние (сумма и количество). Поэтому мы используем тип AggregateFunction:

CREATE TABLE page_performance
(
    page_id UInt32,
    page_name String,
    avg_response_time AggregateFunction(avg, UInt32)  -- Stores the state needed for avg calculation
)
ENGINE = AggregatingMergeTree()
ORDER BY page_id;

Создайте инкрементное материализованное представление, которое будет действовать как триггер вставки для новых данных и хранить промежуточные данные состояния в целевой таблице, определённой выше:

CREATE MATERIALIZED VIEW page_performance_mv
TO page_performance
AS SELECT
    page_id,
    page_name,
    avgState(response_time_ms) AS avg_response_time  -- Using -State combinator
FROM raw_page_views
GROUP BY page_id, page_name;

Вставьте некоторые начальные данные в исходную таблицу, создавая часть на диске:

INSERT INTO raw_page_views (page_id, page_name, response_time_ms) VALUES
    (1, 'Homepage', 120),
    (1, 'Homepage', 135),
    (2, 'Products', 95),
    (2, 'Products', 105),
    (3, 'About', 80),
    (3, 'About', 90);

Вставьте ещё некоторые данные, чтобы создать вторую часть на диске:

INSERT INTO raw_page_views (page_id, page_name, response_time_ms) VALUES
(1, 'Homepage', 150),
(2, 'Products', 110),
(3, 'About', 70),
(4, 'Contact', 60),
(4, 'Contact', 65);

Просмотрите целевую таблицу page_performance:

SELECT 
    page_id,
    page_name,
    avg_response_time,
    toTypeName(avg_response_time)
FROM page_performance
┌─page_id─┬─page_name─┬─avg_response_time─┬─toTypeName(avg_response_time)──┐
│       1 │ Homepage  │ �                 │ AggregateFunction(avg, UInt32) │
│       2 │ Products  │ �                 │ AggregateFunction(avg, UInt32) │
│       3 │ About     │ �                 │ AggregateFunction(avg, UInt32) │
│       1 │ Homepage  │ �                 │ AggregateFunction(avg, UInt32) │
│       2 │ Products  │ n                 │ AggregateFunction(avg, UInt32) │
│       3 │ About     │ F                 │ AggregateFunction(avg, UInt32) │
│       4 │ Contact   │ }                 │ AggregateFunction(avg, UInt32) │
└─────────┴───────────┴───────────────────┴────────────────────────────────┘

Обратите внимание, что колонка avg_response_time имеет тип AggregateFunction(avg, UInt32) и хранит информацию о промежуточном состоянии. Также обратите внимание, что строки данных для avg_response_time не полезны для нас, и мы видим странные текстовые символы, такие как �, n, F, }. Это попытка терминала отобразить двоичные данные как текст. Причина этому заключается в том, что типы AggregateFunction хранят своё состояние в двоичном формате, оптимизированном для эффективного хранения и вычисления, а не для человеческой читаемости. Это двоичное состояние содержит всю информацию, необходимую для подсчёта среднего.

Чтобы использовать его, воспользуйтесь комбинатором Merge:

SELECT
    page_id,
    page_name,
    avgMerge(avg_response_time) AS average_response_time_ms
FROM page_performance
GROUP BY page_id, page_name
ORDER BY page_id;

Теперь мы видим правильные средние значения:

┌─page_id─┬─page_name─┬─average_response_time_ms─┐
│       1 │ Homepage  │                      135 │
│       2 │ Products  │       103.33333333333333 │
│       3 │ About     │                       80 │
│       4 │ Contact   │                     62.5 │
└─────────┴───────────┴──────────────────────────┘

См. также