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

Нужен совет опытных, Есть таблица CREATE TABLE clicks (

id String,
clicked_date Date DEFAULT toDate(clicked_at),
clicked_at DateTime('UTC'),
campaign_id UUID,
domain_id SimpleAggregateFunction(anyLast, Nullable(UUID)),
referrer SimpleAggregateFunction(anyLast, Nullable(String)),
country SimpleAggregateFunction(anyLast, Nullable(String)),
device SimpleAggregateFunction(anyLast, Nullable(String)),
os SimpleAggregateFunction(anyLast, Nullable(String)),
cost SimpleAggregateFunction(anyLast, Nullable(Float32)),
isVisited SimpleAggregateFunction(anyLast, Nullable(UInt8)),
isTargeted SimpleAggregateFunction(anyLast, Nullable(UInt8)),
meta_value_1 SimpleAggregateFunction(anyLast, Nullable (Decimal(15,8))),
meta_value_2 SimpleAggregateFunction(anyLast, Nullable (Decimal(15,8))),
meta_value_3 SimpleAggregateFunction(anyLast, Nullable (Decimal(15,8)))
)
ENGINE = AggregatingMergeTree
PARTITION BY toYYYYMM(clicked_at)
PRIMARY KEY (id, clicked_date, campaign_id)
ORDER BY (id, clicked_date, campaign_id);

Есть 3 разных набора данных привязанный к id, 3 типа событий происходят в разное время, для примера 30к данных
1. Все колонки (10к)
2. id, clicked_at, campaign_id, cost, isVisited, meta_value_1, meta_value_2, meta_value_3 (10к)
3. id, clicked_at, campaign_id, isTargeted, meta_value_1, meta_value_2, meta_value_3 (10к)


как оптимально вставлять данные? Варианты
- Вставлять все наборы разом приводя к единой схеме и сразу 30к
INSERT INTO clicks (id, clicked_at, campaign_id, domain_id, referrer, country, device, os, cost, isVisited, isTargeted, meta_value_1, meta_value_2, meta_value_3)
VALUES ('c6f06ktmk1u7lohuee00', now(), '11000000-0000-0000-0000-000000000011', '22000000-0000-0000-0000-000000000022','http://example.com', 'Russia', 'nokia', 'windows', null, 0, 0, 0, 10, 0)
('c6f06ktmk1u7lohuee00', now(), '11000000-0000-0000-0000-000000000011', null, null, null, null, null, 10, 1, 0, null, null, 20)
('c6f06ktmk1u7lohuee00', now(), '11000000-0000-0000-0000-000000000011', null, null, null, null, null, null, null, 1, null, null, null)

- Вставлять каждый набор по отдельности по 10к?
INSERT INTO clicks (id, clicked_at, campaign_id, domain_id, referrer, country, device, os, cost, isVisited, isTargeted, meta_value_1, meta_value_2, meta_value_3)
VALUES ('c6f06ktmk1u7lohuee00', now(), '11000000-0000-0000-0000-000000000011', '22000000-0000-0000-0000-000000000022','http://example.com', 'Russia', 'nokia', 'windows', null, 0, 0, 0, 10, 0)

INSERT INTO clicks (id, clicked_at, campaign_id, cost, isVisited, meta_value_1, meta_value_2, meta_value_3)
VALUES ('c6f06ktmk1u7lohuee00', now(), '11000000-0000-0000-0000-000000000011', 10, 1, null, null, 20);

INSERT INTO clicks (id, clicked_at, campaign_id, isTargeted, meta_value_1, meta_value_2, meta_value_3)
VALUES ('c6f06ktmk1u7lohuee00', now(), '11000000-0000-0000-0000-000000000011', 1, null, null, null)

16 ответов

16 просмотров

можно вставлять через mat.view и оно схлопнет в select который вы напишете. INSERT INTO clicks VALUES ( .... now() ) любая функция в секции VALUES выключает stream parser и включает AST парсер, что резко ограничивает возможный размер инсерта (до 256кб) и увеличивает потребление памяти и cpu. Лучше это делать в select в mat.view или задавать default now() в поле.

лучше вставлять одним инсертом

Vitaly- Автор вопроса
Denny [Altinity]
можно вставлять через mat.view и оно схлопнет в se...

Но я скорее не про агрегированную промежуточную таблицу, а raw таблицу Хочу иметь одну таблицу в которой храняться все события как они были, а уже по ней строить агрегации в зависимости от полей и полезных сущностей типа campaign и других Про функцию спасибо👍

максимально гибко - JSONEachRow, тогда хоть 50 наборов

Vitaly- Автор вопроса
Vladimir Goncharov
максимально гибко - JSONEachRow, тогда хоть 50 наб...

А я правильно понимаю что задается полная схема таблицы, но внутри вот эти разные наборы сами разбираются?

Vitaly
А я правильно понимаю что задается полная схема та...

при инсерте схема не задаётся. название колонок и соответсвующие им значения идут в жсонах. у меня 300 колонок, вставляется бесчисленное количество их комбинаций. все схемы на все случаи жизни не описать.

Vitaly- Автор вопроса
Vladimir Goncharov
при инсерте схема не задаётся. название колонок и ...

Пойду смотреть как это через golang driver сделать, чтобы батчами вставлять

Vitaly- Автор вопроса
Vitaly- Автор вопроса
Denny [Altinity]
лучше вставлять одним инсертом

Спасибо, нашел баг, но не уверен что связан с CH, скорее с драйвером go, при вставке в одном батче записей с одинаковым id, мержатся сразу все в одну запись, но с не полными данными

Vitaly- Автор вопроса
Slach [altinity]
смотрите настройку clickhouse optimize_on_insert

Спасибо, работает, потестирую еще

Вы можете использовать формат при вставки JSOMEachRow и тогда вам не придется приводить к одному виду.

Vitaly
Спасибо, работает, потестирую еще

эта фича делает ровно тоже самое при инсерте что и мержи, у вас неправильный order by у таблицы

Vitaly- Автор вопроса
Denny [Altinity]
эта фича делает ровно тоже самое при инсерте что и...

Я насколько правильно понял что order by в AggregatingMergeTree, это уникальный ключ по которому дедупликация происходит, вот я вижу что весь order by совпадает в двух кликах, почему он не правильный? Если этот флаг делает то же самое, почему тогда с включенным работае правильно? И еще такой ньюанс если вставлять в разных батчах уникальные ключи, все тоже работает правильно

Vitaly
Я насколько правильно понял что order by в Aggrega...

AggregatingMergeTree да схлапывает записи по orderby вы делаете два разных инсерта и вставляете по одной записи с одним значением ключа, мерж позже схлопнет эти две записи в одну если сделать один инсерт и вставить 2 записи сразу, то они прямо инсертом схлопнутся в одну, этот параметр просто позволяет переключать, делать схлапывание в инсерте или нет. И этот параметр жутко замедляет инсерты.

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

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

Есть какой-нибудь для Delphi/FPC T*Compression(Decompression)Stream на базе LZ4/Zstd/любой другой быстрый(и хорошо сжимающий) алгоритм А ещё лучше в pure pascal А ещё лучше од...
notme
48
А чем вам питонисты не угодили?😂
.
79
type TObj = object procedure Init; virtual; end; TObj1 = object(TObj) procedure Init; override; end; procedure TObj1.Init; begin inherited; end; procedur...
Alexander 👋
29
Такой вопросец - есть функция function MySuperDuperConcat(const a: array of AnsiString): AnsiString; Как мне в её теле сделать вот так? Result:=Concat(a); А не грустный вариан...
notme
15
Всем привет. Поделитесь, пожалуйста, опытом. Есть форма, на которой имеется dbgrid и кнопки: добавить, редактировать, удалить. Если нет записей в dbgrid, то кнопки редактирова...
Евгений
5
type TExtensions<GExtender>=class function GetExtension<GEntityExtenderType>:GEntityExtenderType; end; function TExtensions<GExtender>.GetExtension<GEntityExtenderType...
zamtmn
8
Всем привет, написал код ниже, но он выдает сегфолт, в чем причина? #include <stdio.h> #include <stdlib.h> #include <string.h> struct product { char *name; float price; };...
buzz базз
86
Всем привет, препод задал вопрос, подскажите пожалуйста, какой адрес инкапсулирует указатель?
Свинка Пеппа
7
Почему никто ещё не написал квантовую виртуальную машину на Windows?
КТ315
7
Вот смотрите у меня есть два стрима сейчас fs, cs: TStream; fs := TFileStream.Create('filename'); cs := TCompressionStream.Create(compression_level, fs); Я хочу сделать так: ...
notme
5
Карта сайта