временными рядами с несколькими метриками. Эти метрики будут агрегироваться по временным интервалам.
Какая архитектура таблицы будет быстрее обрабатывать запрос на агрегацию?
Варианты таблиц и запросов:
1.
CREATE TABLE table
(
id UInt32,
timecode DateTime,
metric_1 Float32,
metric_2 Float32,
metric_3 Float32
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(timecode)
ORDER BY (id, timecode);
SELECT id,
toStartOfInterval(timecode, toIntervalMinute(30)) AS timecode_,
avg(metric_1) AS metric_1,
avg(metric_2) AS metric_2,
avg(metric_3) AS metric_3
FROM table
GROUP BY id, timecode_;
—————————————————————-
2.
CREATE TABLE table
(
id UInt32,
metric_id UInt16,
timecode DateTime,
value Float32
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(timecode)
ORDER BY (id, metric_id, timecode);
SELECT id,
metric_id
toStartOfInterval(timecode, toIntervalMinute(30)) AS timecode_,
avg(value) AS value
FROM table
GROUP BY id, metric_id, timecode_;
——————————————————————————————
Интуитивно, 2 вариант должен быть быстрее, но есть сомнения.
Во втором варианте больше бакетов. Обычно это плохо. Но в первом размер бакета больше. Так что лучше проверить на ваших данных. Так-же решение зависит от доступной RAM и состояния optimize_aggregation_in_order. Очень странно что у вас нет WHERE. Вы правда всю таблицу читаете и аггрегируете?
WHERE обязательно будет, я убрал его из примера.
А зря. Это самый важный вопрос при выборе ORDER BY таблицы. Для GROUP BY запросов это не столь важно (особенно если вы не используете optimize_aggregation_in_order)
Было предположение, что во втором случае данные на диске хранятся ближе, а значит их чтение должно быть быстрее.
а это предположение верное, или я заблуждаюсь?
Я же говорю, все эти предположения имеют смысл только в контексте WHERE. Так как вы показали - все равно. 100% данных будет считано из таблицы для агрегации. Еще можно подискутировать про уровень компрессии, для близкорасположенных данных при разных вариантах ORDER BY, но тут снова проще измерить на реальных.
Обсуждают сегодня