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 ответов

22 просмотра

Не знаю, подойдёт или нет. Но ведь в 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- Автор вопроса

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

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

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта