наполнение одинаковое, различаются только ключом партиционирования.
Первая:
CREATE TABLE TestTable
(
event_id UUID,
event_date Date,
event_type LowCardinality(String),
event_region LowCardinality(String),
minValueState AggregationFunction(min, Int8),
recordsNumState AggregationFunction(count)
)
ENGINE = AggregationMergeTree()
PARTITION BY toYYYYMMDD(event_date)
ORDER BY (event_date, event_type, event_region)
TTL event_date + interval 30 day
Вторая:
PARTITION BY (toYYYYMMDD(event_date), event_type, event_region)
В таблице сейчас всего 2 млрд записей, в день пишется 500 млн, ожидаемый рабочий размер - 15 млрд записей. Все запросы представляют из себя либо выбор event_id по нужным (event_date, event_type, event_region) с заданным значением агрегата min, либо подсчёт выбранных таким образом уников.
Тестовый запрос:
SELECT
t.event_id
FROM
TestTable t
WHERE
t.event_date = '2021-01-25'
and t.event_type = 'event1'
and t.event_region = 'Msk'
GROUP BY
t.event_id
HAVING
minMerge(t.minValueState) > 0
Результат для первой таблицы:
read_rows = 50.0 млн
memory_usage = 6.23 гб
Результат для второй таблицы:
read_rows = 49.8 млн
memory_usage = 5.71 гб
Правильно понимаю, что в первом варианте КХ ищет по засечкам нужную часть партиции, которая, благодаря ключу сортировки, получается лишь немного больше нужной партиции во втором варианте, и работает только с ней?
Я предполагал, что второй вариант будет сильно быстрее, но такая оптимизация в моём случае практически бесполезна. А в каких случаях разбиение на более мелкие партиции имеет смысл для ускорения запросов? Или я вообще делаю что-то не так?
Помогите, пожалуйста, с этим вопросом.
партиционирвание сделано не для ускорения запросов в первую очередь, а для манипуляций
Опыты с составными ключами в partition by, подобные PARTITION BY (toYYYYMMDD(event_date), event_type, event_region) у меня ни к чему хорошему не привели. Во первых сильно стала проседать скорость, когда обьём данных накопился более-менее приличный, несколько лет. Партиций стало слишком много. И во вторых, пришлось увеличивать max_partitions_per_insert_block со 100 до 1000+, иначе при вставке репликация ставала колом, реплики просто не принимали такие запросы, и пока я не заметил, их в буфере Distributed накопилось уже приличное количество, и они бесконечно пытались раскидаться по шардам. После увеличения max_partitions_per_insert_block оно, конечно, рассосалось, но деградация скорости стала такой, что просто перелили с простым партицированием по месяцам. А дневные юзаются для кеш-таблиц, в которые триггером копируется из основных таблиц. Дневные - чтобы по крону раз в сутки можно было чистить кеш. Вот такой опыт получился.
Все правильно вы поняли. Обычно невозможно напихать столько полей в partition by потому что будет очень много партов и замедляются инсетры. Чаще всего удается добавить в partitiin by какое-то одно низкокардинальное поле которое не хочется класть в order by
Спасибо за ваш опыт, учту. У меня просто есть таблицы, созданные с кривыми ключами сортировки, и там добавление условия по полю из ключа партиционирования ускоряет запросы иногда в десятки раз. И есть много однотипных таблиц, которые хочу схлопнуть без потери скорости работы с ними.
Обсуждают сегодня