184 похожих чатов

Добрый день. Подскажите статьи или ссылки на треды, где можно

почитать, как добиться высокого QPS с хорошим временем выполнения запроса и не утилизировать CPU до 100%.

Есть нетривиальная задача: Таблица collapsingMT необходимо сделать достаточно быструю вставку, а также быструю выборку.
В текущем варианте таблица выглядит так:

CREATE TABLE default.tab1
(
`id` UInt64,
`vid` UInt8,
`stat` UInt8,
`type` UInt32,
`customer_id` UInt32,
`param` Decimal(15, 5),
`id_se` UInt64,
`value1` Decimal(16, 2),
`value2` Decimal(16, 2),
`sign` Int8,
`dt_save_row` DateTime64(3) DEFAULT now64()
)
ENGINE = ReplicatedCollapsingMergeTree('/clickhouse/tables/tab1', '{replica}', sign)
PARTITION BY intDiv(id, 50000000)
ORDER BY (id_se, id, vid, stat, type)
SETTINGS index_granularity = 8192;

id_se почти все уникальные, id неуникальные, остальные поля неучавтсвуют в collapsing.
id_se стоит на 1ом месте в ORDER BY, так как вставка отмены строки происходит через поиск того, что там уже лежит, если поставить в конец ORDER BY, то скорость вставки медленная.
Все селекты с условием по id отдает быстро, но как только QPS поднимаем до 30-40, то CPU утилизируется под 100% и скорость selectов падает кратно(К примеру 10-15 qps отдает за 25-30ms, когда 30-40qps то запрос выполняется в диапазоне 500-800ms). 36 физических ядер, диск ssd, кол-во строк 800млн.

Какие есть варианты добиться высокого и быстрого qps, при быстрой вставке ?

30 ответов

9 просмотров

Не знаю, подойдёт или нет. Но ведь в 22.5 или более ранней версии завозили функционал лимита нагрузки от пользователя.

Clir- Автор вопроса

запустите clickhouse-benchmark на чтение, поставьте 30 параллельных запросов, потом поиграйте с настройками SET max_threads=1, merge_tree_coarse_index_granularity=2 (or 1) > PARTITION BY intDiv(id, 50000000) Возможно партиционирование по id_se будет лучше, тк на анализ индекса будет тратиться меньше времени. index_granularity тоже можно опустить до 1024-2048

Clir- Автор вопроса
Dmitry [Altinity] Titov
запустите clickhouse-benchmark на чтение, поставьт...

партиции сделал по id, чтобы выборки по id давали быстрый ответ. Вставки кстати в этот сервер не идут, на этой реплике только select. Если id_se поставлю в партицию, а id на первое место, кмк скорость селектов по id станет медленнее(

Clir- Автор вопроса
Dmitry [Altinity] Titov
запустите clickhouse-benchmark на чтение, поставьт...

еще тут https://altinity.com/blog/clickhouse-in-the-storm-part-2 про use_uncompressed_cache написано, у нас памяти вагон(400ГБ есть свободных). Выставить в 1 и size поднять с 8ГБ может помочь?

Clir
еще тут https://altinity.com/blog/clickhouse-in-th...

Не уверен, если у вас там реально рандомный доступ

Clir- Автор вопроса
Dmitry [Altinity] Titov
запустите clickhouse-benchmark на чтение, поставьт...

партиционирование по id только хуже сделало( max_threads=1 помогает, утилизация 40-45% при qps=40. Запросы конечно выполняются 250-400ms в среднем. merge_tree_coarse_index_granularity как будто почти не влияет( index_granularity=1024 тоже практически не помогает

Clir
партиционирование по id только хуже сделало( max_t...

merge_tree_coarse_index_granularity как будто почти не влияет( Мне помогало процентов на 20-30, когда анализ индекса занимает значительное время по сравнению с самим запросом. А покажи сам SELECT запрос и сколько партиций у вас?

Clir- Автор вопроса
Dmitry [Altinity] Titov
merge_tree_coarse_index_granularity как будто почт...

партиций 8 Вот запрос, находу агрегирую collapsing select id, vid, stat, type, customer_id, param, toDecimal64(sum(sumin),2) as sumin, toDecimal64(sum(sumpv),2) as sumpv, uniqExact(id_se) as count, toDateTime(max(dt_save_row)) as maxver from ( SELECT gameid, vid, stat, type, customer_id, param, id_se, toDecimal64(sum(value1*sign),2) as sumin, toDecimal64(sum(value2*sign),2) as sumpv, dt_save_row FROM default.tab1 t WHERE id in (379248981) group by id, vid, stat, type, customer_id, param, id_se, dt_save_row having sum(sign)!=0) group by id, vid, stat, type, customer_id, param;

Clir- Автор вопроса
Dmitry [Altinity] Titov
merge_tree_coarse_index_granularity как будто почт...

если так то да, помогает примерно на 10% не больше. То есть утилизация вместо 50% стала 45%

Clir
партиций 8 Вот запрос, находу агрегирую collapsing...

Хм, я скорее про тот который SELECT делает по id_se

Clir
партиций 8 Вот запрос, находу агрегирую collapsing...

Кстати не думали сделать реверс индекс просто?

Clir- Автор вопроса
Dmitry [Altinity] Titov
Хм, я скорее про тот который SELECT делает по id_s...

так это же на вставку только для отмены строк состояния: insert into default.tab1 select *, negate(sign) from default.tab1 where id_se in (перечень id_se передаваемый сервисом)

Clir- Автор вопроса
Clir
подробнее чуть можно, что имеете ввиду?

Сделать таблицу с маппингом (id_se -> id) (ну над ток определится в каком порядке) Тогда можно через подзапрос доставать нужный id (или id_se) WHERE id IN (379248981) заменится на WHERE id IN (379248981) AND id_se IN (SELECT id_se FROM reverse_index WHERE id = 379248981))

Clir- Автор вопроса
Dmitry [Altinity] Titov
Сделать таблицу с маппингом (id_se -> id) (ну над ...

да, я просто упростил, уже есть такая таблица именно так запрос и построен) У нас при вставке сюда сразу льется в отдельную таблицу, которая у нас как индексная, только мы ее используем и для других запросов. там id_se+id лежит.

Clir- Автор вопроса
Dmitry [Altinity] Titov
Сделать таблицу с маппингом (id_se -> id) (ну над ...

но вот хороший вариант по двум условия фильтроваль, мы только по 2му из вашего примера

Clir
да, я просто упростил, уже есть такая таблица имен...

А у вас что более важно то? Сейчас у вас таблица оптимизирована для вставки больше, чем на чтение

Clir
партиций 8 Вот запрос, находу агрегирую collapsing...

8 партиций на 800 млн строк то есть, так как id_se high-cardinality колонка, любой запрос с id=... сканит 100 млн строк не было идеи сделать партиции поменьше?

Clir
но вот хороший вариант по двум условия фильтроваль...

Ну тогда вот вам еще на попробовать WHERE indexHint(id IN (379248981)) AND id_se IN (SELECT id_se FROM reverse_index WHERE id = 379248981)) WHERE id IN (379248981) AND indexHint(id_se IN (SELECT id_se FROM reverse_index WHERE id = 379248981)))

Clir- Автор вопроса
ivan
8 партиций на 800 млн строк то есть, так как id_se...

так и есть, 150-160млн строк сканит при запросах

Clir
так и есть, 150-160млн строк сканит при запросах

Так вы делаете условие же на id_se как я понял, не должно 100 лям сканировать

Dmitry [Altinity] Titov
Так вы делаете условие же на id_se как я понял, не...

как я понял, для пре-вставки условие по id_se для последующего чтения — по id

ivan
как я понял, для пре-вставки условие по id_se для ...

Да, но судя по этому > Сделать таблицу с маппингом (id_se -> id) (ну над ток определится в каком порядке) да, я просто упростил, уже есть такая таблица именно так запрос и построен)

Clir- Автор вопроса
Dmitry [Altinity] Titov
Так вы делаете условие же на id_se как я понял, не...

запрос на чтение выглядит так и судя по clickhouse-benchmark у него rps 100-150млн К примеру вот такой запрос: select id, vid, stat, type, customer_id, param, toDecimal64(sum(sumin),2) as sumin, toDecimal64(sum(sumpv),2) as sumpv, uniqExact(id_se) as count, toDateTime(max(dt_save_row)) as maxver from ( SELECT gameid, vid, stat, type, customer_id, param, id_se, toDecimal64(sum(value1*sign),2) as sumin, toDecimal64(sum(value2*sign),2) as sumpv, dt_save_row FROM default.tab1 t WHERE id_se(select id_se from index_table where id in (379248981)) group by id, vid, stat, type, customer_id, param, id_se, dt_save_row having sum(sign)!=0) group by id, vid, stat, type, customer_id, param;

Clir
запрос на чтение выглядит так и судя по clickhouse...

> него rps 100-150млн != что каждый запрос читает 100 лям строк)

Clir
запрос на чтение выглядит так и судя по clickhouse...

У вас тут кх все партиции читает, так что добавить indexHint(id in (379248981)) поможет читать меньше данных

Clir- Автор вопроса

Похожие вопросы

Обсуждают сегодня

здравствуйте. совершаю вот такую вещь: strcpy(line, (char)current_number); где current number — неподписанный шорт, line — массив чаров. ругань следующая: main.c:29:30: error...
Roberto's Ширгозиев
13
я не магистр хаскеля, но разве не может лейзи тип конвертнуться в не-лейзи запросив вычисление содержимого прям при инициализации?
deadgnom32 λ madao
100
@MrMiscipitlick А можешь макрос написать, который будет вычислять смещение относительно переданных меток? Просто .label1-.label2, и вернуть значение.
КТ315
35
Можно попросить небольшое ревью кода? Тут немнога, я ничего интереснее не придумал, чем написать аналог tree в качестве практики с cmake. https://github.com/hrimov/tree-unix/...
Andrew Hrimov
11
Всем привет. Ребят подскажите пожалуйста. Вопрос по дизасемблировани. Начну с начала. У меня есть скомпилированная программа на ГО (я разработчик) - в ней есть защита лицензии...
Zloy
11
А еще в перле можно уже @arr1 + @arr2?
Sergei Zhmylove
53
Привет всем. появился вопрос. Разрабатываю сайт, в данный момент он запущен. Хостинг beget. Добавляю на сайт яндекс метрику с помощью полей client-settings (взято отсюда http...
Andrew
2
кто тебе сказал, что она угроблена? многие только начинают жизнь, после увольнения из Гугла, Майкрософта, Оракла,...
Alex Kom
9
В альтернативе у нас сидеть горбатиться на дядю в галерах, пока не помрешь или пока тебя не заменят более молодым сотрудником, который готов гребсти в два раза дешевле. Вот и ...
Кабан Кабанов
7
все привет. подскажите может кто сталкивался evo 3 если в formlister в параметр formTpl указать имя чанка а не через @CODE то в указанном чанке не парсятся плейсхолдеры [**]? ...
Иван Тарасевич
6
Карта сайта