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

Добрый день, здравствуйте! Можете, пожалуйста помочь. Таблица работает на движке ReplacingMergeTree,

логика такая: у нас есть компонент в системе, который выполняет какую-то работу, попутно сохраняя "снимки" данных в процессе. Условно, начал работу — сделал снимок, произошло какое-то событие в системе — сделал снимок и так далее. Идея ясна. Все они имеют почти идентичные значение полей (например, отличается last_event_time).

У клиента есть желание видеть самые актуальные значения в реальном времени. В базе у нас содержатся "дубликаты", из которых нужно выбрать один самый актуальный. При каждом запросе чистить дубликаты (а Clickhouse это позволяет) слишком дорого. Для меня решением стал запрос:

SELECT
argMax(hex(id), last_event_time)
argMax(field_1, last_event_time),
argMax(field_2, last_event_time),
FROM (
SELECT id, field_1, field_2, field_3, last_event_time -- ...
FROM table_1
WHERE (service_timestamp > toDateTime64('1694165200', 6, 'UTC') AND service_timestamp < toDateTime64('1696957199', 6, 'UTC'))
UNION ALL
SELECT id, field_1, field_2, field_3, last_event_time -- ...
FROM table_2
WHERE (service_timestamp > toDateTime64('1694165200', 6, 'UTC') AND service_timestamp < toDateTime64('1696957199', 6, 'UTC'))
)
GROUP BY (id)
ORDER BY (service_timestamp) ASC
LIMIT 0, 100;

argMax() вернет строку m с максимальным значением n.

m | n
1 | 2
1 | 3
2 | 4
4 | 4

SELECT argMax(m, n) .. GROUP BY (m)
===============================
1 | 3
2 | 4
4 | 4

Однако при большом наборе полей памяти используется невероятно много. Вопрос: как обычно решается такая проблема? Именно Best Practice.

Я не администратор, опыта работы с базами данных у меня мало. Буду признателен за помощь!

10 ответов

31 просмотр

argMax вполне good practice. Еще вариант, выбрать максимальное значение timestamp и сджойнить с основной таблицей SELECT * FROM (SELECT * FROM table) as full RIGHT SEMI JOIN (SELECT max(service_timestamp) as service_timestamp, id ) as maxTime USING service_timestamp, id

Алексей Осипов
Не тяжеловатый джойн будет ?

С ограничениями по Where нормально. В чистом виде конечно не пойдет

из БД в ПЗУ такое грести накладно.. Проще на коленке написать отдельную приложуху на любом ЯП или использовать Redis и постоянно обновлять по ключу данные.. Тоже пример "на котиках", но логику вы поймёте: есть N светофоров - id 1, 2, 3,... и в каждый момент времени у вас поступает связка: (id, сигнал(зел/жел/кр), timestamp) -> в редиску перезаписывать для каждого id: 1, кр, 1696912696 3, зел, 1696912697 ... Если у вас ваши поля НЕ огромные, вы там не храните видео и прочее и оборудования - не миллиарды миллиардов, тогда вы в каждый момент времени имеете САМЫЕ просто актуальные данные и достаточно получить их из редиски той же по ключу - это считанные миллисекунды, даже учитывая, если у вас редиска будет далеко.. А как вам советуют с джойнами и прочим - это накладно ОЧЕНЬ - "из пушки по воробьям". Посмотрите в сторону in-memory хранения последнего стейта, чтоб не выгребать.. БД всё же нужна для ретроспективы у вас, а не для последнего стейта..

Владислав-Белоусов Автор вопроса
DaiTenshi
из БД в ПЗУ такое грести накладно.. Проще на колен...

Приложение, которое генерирует снимки данных, как раз работает с Redis. И занимается планированием — там он к месту. А Clickhouse работает в качестве исторической справки. Тут он используется по назначению: клиенты могут захотеть выгрузить и посмотреть на историю за прошлую неделю, месяц или даже год. Тут Redis не поможет, к сожалению)

Владислав Белоусов
Приложение, которое генерирует снимки данных, как ...

Для ретро - запрос в клик, последнее в редиске в качестве хранилища ключ-значение. Видимо, там редиска используется как мессадж бас. А раз редиска уже есть, почему бы не выделить там ещë kvp хранилище? Я не говорил, что вам не нужна ретроспектива, но для последних значений лучшей практикой будет подрубить in-memory kvp хранилище.

Владислав-Белоусов Автор вопроса
DaiTenshi
Для ретро - запрос в клик, последнее в редиске в к...

Слишком большой объём данных. У нас огромный трафик, и Clickhouse себя зарекомендовал великолепно) С этим помощь не нужна, спасибо). Мне нужна только помощь с оптимизацией запроса)

Сделать mv с AggregatingMT движком и argMaxState не вариант? У нас похожий кейс, нужно выдавать статусы на максимальную дату, по сути текущие статусы. Уникальных записей под полмиллиона, размер - единицы гигабайт за год на диске всего

Владислав-Белоусов Автор вопроса
Ivan Torgashov
Сделать mv с AggregatingMT движком и argMaxState н...

Я в эту сторону не смотрел, спасибо, обязательно посмотрю. Тут как раз выше кидали статью с MV. А насколько ощутима разница между "оптимизированным запросом" и MV было в вашем случае, если не секрет? Я вот добился неплохой производительности просто добавив LIMIT внутрь подзапроса: SELECT argMax(hex(id), last_event_time) argMax(field_1, last_event_time), argMax(field_2, last_event_time), FROM ( SELECT id, field_1, field_2, field_3, last_event_time -- ... FROM table_1 WHERE (service_timestamp > toDateTime64('1694165200', 6, 'UTC') AND service_timestamp < toDateTime64('1696957199', 6, 'UTC')) LIMIT 0, 100; -- добавил тут UNION ALL SELECT id, field_1, field_2, field_3, last_event_time -- ... FROM table_2 WHERE (service_timestamp > toDateTime64('1694165200', 6, 'UTC') AND service_timestamp < toDateTime64('1696957199', 6, 'UTC')) LIMIT 0, 100; -- добавил тут ) GROUP BY (id, ...) ORDER BY (...) ASC LIMIT 0, 100;

Владислав Белоусов
Я в эту сторону не смотрел, спасибо, обязательно п...

в исходной таблице несколько миллиардов записей, допустим для миллиона уникальных клиентов. При аггрегации все это схлапывается до миллиона получается, по ним и идёт поиск по дата+стейт, либо просто стейт (в нашем случае с датой), даже за год всего 365млн строк, боюсь даже посчитать сколько в сырой будет за это время (храним макс. несколько месяцев оригинал). Так вот по MV поиск по конретному клиенту менее одной секунды, по сырью ддо нескольких минут, в зависимости от нагрузки

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

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

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
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
Карта сайта