@clickhouse_ru

Страница 618 из 723
fikfok
10.08.2018
12:54:08
У меня было что-то похожее, по моей вине, некоторые данные просто дублировались из-за неправльной репликации. Проверь запросом GROUP BY по какому нибудь уникальному полю
У меня таблица сама по себе, репликации нет. Проверил итоги на одном id, ситуация всё та же: общие итоги сходятся, а группировка по toStartOfFifteenMinutes даёт разное кол-во записей.

Kirill
10.08.2018
13:31:40
Коллеги, добрый день! Никто не сталкивался с таким явлением с матвью. Есть два идентичных по результату запроса: один к таблице с детальными данными, второй к матвью. Запрос к таблице с детальными данными отрабатывает быстрее чем к матвью. Это первое. И второе. В обоих запросах использутеся функция toStartOfFifteenMinutes. Так вот, запрос к детальным данным возвращает одно количество строк, а запрос к матвью в 10 раз меньше. Т.е. второй запрос пропускает какие-то времена. Хотя общие итоги совпадают. Я перестал что-то понимать в матвью. У кого-то было что-то подобное? П.С. Матвью создавалось на рабочей боевой таблице с ключевым словом populate. Т.е. во время работы команды CREATE MATERIALIZED VIEW... данные понемногу загружались в таблицу с детальными данными небольшими порциями (сотни-несколько тысяч записей в минуту, записываются не непрерывно, а квантами). Про то что таблицу надо "останавливать" для CREATE в курсе. Но в итоге общие count и uniq на таблице с детальными данными и матвью совпадают, потому сделал вывод, что рабочий процесс по загрузке данных не повлиял на матвью и данные не потерялись.
Как выглядит запрос на создание въюхи, какие запросы делаете и что ожидаете увидеть?

fikfok
10.08.2018
13:39:13
Как выглядит запрос на создание въюхи, какие запросы делаете и что ожидаете увидеть?
Создание: CREATE MATERIALIZED VIEW td_stats.mvw_td_stats_site_zone_position_all_resp_by_15minute ENGINE = AggregatingMergeTree(created_date, (created_date, position_id), 8192) POPULATE as select created_date, toStartOfFifteenMinutes(created) as created_15minute, site_id, zone_id, position_id, countState() as total, uniqState(user_id) as unique from td_stats.td_stats group by created_date, toStartOfFifteenMinutes(created), site_id, zone_id, position_id Запрос к матвью (время работы ~450 мс): select created_15minute as date, toInt32(countMerge(total)) as total, toInt32(uniqMerge(unique)) as unique from td_stats.mvw_td_stats_site_zone_position_all_resp_by_15minute where position_id = 6103 group by created_15minute order by created_15minute Запрос к таблице с детальными данными (время работы ~170 мс !!!): select toStartOfFifteenMinutes(created) as date, toInt32(count()) as total, toInt32(uniq(user_id)) as unique from td_stats.td_stats where position_id = 6103 group by toStartOfFifteenMinutes(created) order by toStartOfFifteenMinutes(created)

Google
Kirill
10.08.2018
13:47:48
Создание: CREATE MATERIALIZED VIEW td_stats.mvw_td_stats_site_zone_position_all_resp_by_15minute ENGINE = AggregatingMergeTree(created_date, (created_date, position_id), 8192) POPULATE as select created_date, toStartOfFifteenMinutes(created) as created_15minute, site_id, zone_id, position_id, countState() as total, uniqState(user_id) as unique from td_stats.td_stats group by created_date, toStartOfFifteenMinutes(created), site_id, zone_id, position_id Запрос к матвью (время работы ~450 мс): select created_15minute as date, toInt32(countMerge(total)) as total, toInt32(uniqMerge(unique)) as unique from td_stats.mvw_td_stats_site_zone_position_all_resp_by_15minute where position_id = 6103 group by created_15minute order by created_15minute Запрос к таблице с детальными данными (время работы ~170 мс !!!): select toStartOfFifteenMinutes(created) as date, toInt32(count()) as total, toInt32(uniq(user_id)) as unique from td_stats.td_stats where position_id = 6103 group by toStartOfFifteenMinutes(created) order by toStartOfFifteenMinutes(created)
1) Для данного набора колонок у вас достаточно странный ПК 2) Если версия КХ >= 18.1.0, то смысла использовать AggregatingMergeTree нет, берите Summing и храните стейты только для того что нужно, например тотал легко считается без хранения состояния.

fikfok
10.08.2018
13:56:38
Что ещё не понятно так это общие количества строк - они разные: select count() from ( select toStartOfFifteenMinutes(created) as date, toInt32(count()) as total, toInt32(uniq(user_id)) as unique from td_stats.td_stats where position_id = 6103 group by toStartOfFifteenMinutes(created) order by toStartOfFifteenMinutes(created) ) select count() from ( select created_15minute as date, toInt32(countMerge(total)) as total, toInt32(uniqMerge(unique)) as unique from td_stats.mvw_td_stats_site_zone_position_all_resp_by_15minute where position_id = 6103 group by created_15minute order by created_15minute ) Первый возвращает 1374, второй - 127.

Denis
10.08.2018
14:33:41
toInt32(uniq(user_id)) as unique -- это нельзя посчитать в MV. u +u+u 1+1+1 = 3, а должно быть 1

fikfok
10.08.2018
14:42:11
toInt32(uniq(user_id)) as unique -- это нельзя посчитать в MV. u +u+u 1+1+1 = 3, а должно быть 1
В самом матвью для подсчёта уников использую uniqState(user_id). А в запросе к матвью использую uniqMerge(unique).

Denis
10.08.2018
14:43:00
ясно, я не заметил.

но тогда как уже правильно заметили в order by нужен created_15minute чтобы для каждого значения created_15minute хранились стейты

fikfok
10.08.2018
14:55:25
но тогда как уже правильно заметили в order by нужен created_15minute чтобы для каждого значения created_15minute хранились стейты
Всё так и есть. В матвью такой group by: group by created_date, toStartOfFifteenMinutes(created), site_id, zone_id, position_id

Denis
10.08.2018
14:57:43
блин, в моей голове новый синтаксис partition by order by, я про ключ схлапывания AggregatingMergeTree, который PK aka sortkey AggregatingMergeTree(created_date, (created_date, position_id, created_15minute)

fikfok
10.08.2018
14:59:38
> > AggregatingMergeTree(created_date, (created_date, position_id, created_15minute) Надо будет попробовать. Спасибо за совет!

Denis
10.08.2018
15:03:08
ну и если вы пишете group by created_date, toStartOfFifteenMinutes(created), site_id, zone_id, position_id то логично все тоже самое перечислить и в PK

тогда агрегаты будут хранится для всех комбинаций значений created_date, toStartOfFifteenMinutes(created), site_id, zone_id, position_id

fikfok
10.08.2018
15:07:14
ну и если вы пишете group by created_date, toStartOfFifteenMinutes(created), site_id, zone_id, position_id то логично все тоже самое перечислить и в PK
Да, матвью с таким определением AggregatingMergeTree(created_date, (created_date, created_15minute, position_id), 8192) POPULATE возвращает такое же количество записей как и запрос к таблице с детальными данными. Хоть с этим разобрался. Но время выполнения почему-то больше у матвью. У матвью около 800 мс, у запроса к таблице с детальными данными около 170 мс.

Google
Denis
10.08.2018
15:10:00
скорее всего uniqMerge работает медленно. сколько строк во вью и сколько в таблице? optimize final ?

быстро будет потом, когда не нужно будет ходить в таблицу и считать count поднимая данные за месяц, можно будет сходить во вью и посчитать сумму, взяв готовые каунты для всех 15 мин. интервалов, т.е. когда во вью будет млн строк, а в таблице миллиард.

а хотя с другой стороны, может и не будет быстрее, надо же все равно домерживать, т.е. во вью будет u,u1,u2,u4 u,u1,u2,u3 u11,u111

fikfok
10.08.2018
15:21:36
скорее всего uniqMerge работает медленно. сколько строк во вью и сколько в таблице? optimize final ?
В матвью - 476 078 записей. В таблице с детальными данными - 299 304 710 записей.

Запустил optimize table td_stats.TMP_mvw_td_stats_site_zone_position_all_resp_by_15minute final Теперь запрос к матвью отрабатывает за около 1.6 с. Время увеличилось вдвое. Что я делаю не так?

Denis
10.08.2018
15:36:46
не знаю, вот мой тест 0.009 MV vs 0.148 Table drop table z; drop table mvz; create table z(d Date, u String) Engine=MergeTree partition by tuple() order by tuple(); CREATE MATERIALIZED VIEW mvz ENGINE = AggregatingMergeTree(d, (d), 8192) as select d, uniqState(u) as us from z group by d insert into z select today(), concat('usr',toString(rand()%664579)) from numbers(10000000); insert into z select today()-1, concat('usr',toString(rand()%664579)) from numbers(10000000); select (uniqMerge(us)) as unique from mvz group by d order by d; ┌─unique─┐ │ 662715 │ │ 662715 │ └────────┘ 2 rows in set. Elapsed: 0.009 sec. select (uniq(u)) as unique from z group by d order by d; ┌─unique─┐ │ 662715 │ │ 662715 │ └────────┘ 2 rows in set. Elapsed: 0.148 sec. Processed 20.00 million rows, 396.65 MB (135.45 million rows/s., 2.69 GB/s.)

правда у меня строки схлапываются и во вью совсем мало строк (CH 18.6.0)

ну и если строк много и все запросы типа where position_id = 6103, я бы position_id поставил первым в PK чтобы спускаться сразу к нему

fikfok
10.08.2018
15:49:36
матвью пересоздал с прежним ключём. Время запроса по конкретному position_id прежнее - около 700-800 мс. Пересоздал матвью с ключом, в котором position_id поставил на первое место. Время выполнения запроса по position_id стало лучше - около 350 мс. Но всё равно, на таблице с детальными данными запрос отрабатывает быстрее - 170 мс.

Denis
10.08.2018
15:55:33
ОК. А сколько строк и какое время select count() from td_stats.mvw_td_stats_site_zone_position_all_resp_by_15minute where position_id = 6103

fikfok
10.08.2018
15:58:39
select count() from td_stats.TMP_mvw_td_stats_site_zone_position_all_resp_by_15minute where position_id = 6103 1 374 стр. За 12 мс. select count() from td_stats.td_stats where position_id = 6103 1 862 345 стр. За 22 мс.

Denis
10.08.2018
16:02:24
тогда сделайте еще одно вью без site_id, zone_id иначе неравноценное сравнение

fikfok
10.08.2018
16:07:21
тогда сделайте еще одно вью без site_id, zone_id иначе неравноценное сравнение
Матвью с только position_id: CREATE MATERIALIZED VIEW td_stats.TMP_mvw_td_stats_only_position_all_resp_by_15minute ENGINE = AggregatingMergeTree(created_date, (position_id, created_date, created_15minute), 8192) POPULATE as select created_date, toStartOfFifteenMinutes(created) as created_15minute, position_id, countState() as total, uniqState(user_id) as unique from td_stats.td_stats group by created_date, toStartOfFifteenMinutes(created), position_id Запрос с выбором конкретного position_id: select created_15minute as date, toInt32(countMerge(total)) as total, toInt32(uniqMerge(unique)) as unique from td_stats.TMP_mvw_td_stats_only_position_all_resp_by_15minute where position_id = 6103 group by created_15minute order by created_15minute Время выполнения около 500 мс. Стало хуже.

Denis
10.08.2018
16:32:49
ну не знаю, возможно у вас такие хитрые юзеры, может из-за времени, у меня MV делает таблицу, и если много уникальных пользователей и если мало https://gist.github.com/den-crane/a72614fbe6d23eb9c2f1bce40c66893f

fikfok
10.08.2018
16:46:42
ну не знаю, возможно у вас такие хитрые юзеры, может из-за времени, у меня MV делает таблицу, и если много уникальных пользователей и если мало https://gist.github.com/den-crane/a72614fbe6d23eb9c2f1bce40c66893f
user_id - fixedstring(24) Так же есть hash_user_id - UInt64, содержит результат выражения sipHash64(toString(user_id)). Пересоздал матвью с использованием этого хеша - uniqState(hash_user_id) as unique. В итоге время чуть лучше стало, но не существенно. И на том большое спасибо! Будем думать дальше.

Necromant
10.08.2018
19:04:12
свопит может? Но 16 ГБ вообще не вариант если данных много, и ssd не поможет, потому что запросы выполняются в памяти, тупо будет падать каждый второй запрос.
примерно так и происходит. Сейчас база еще наполнена примерно только на 30%, объем базы уже привысил 300Тб. Вот про ссд впервые подумал, когда по статистике I/O увидел то, что CH занимает почти весь тайминг у HDD. Потом решил усомниться в своем предположении. На моей практике это первый проект с такими объемами. Толком вот не знаю, сколько по хорошему надо рессурсов и каких

Denis
10.08.2018
19:09:49
300 T или 300 Г ? От запросов зависит и их количества, посчитать тяжело, просто 16 сильно мало, особенно если запросы будут перетряхивать 300Г а потом агрегировать в памяти например 10, наверняка у вас под кеш линукса осталось 4.

Necromant
10.08.2018
19:10:39
300Gb, опечатался

Google
Necromant
10.08.2018
19:11:49
тоесть я правильно понимаю, что больше важна тут ОЗУ, чем само дисковое хранилище?

Alexey
11.08.2018
01:34:13
Доброе утро, правильно я понимаю, что после INSERT батча в MergeTree движках новые данные для SELECT будут доступны сразу после завершения INSERT. Но если я хочу использовать специфику типа Summing/Collapsing/Replacing то мне нужно чтоб случился merge либо ипользовать FINAL ?

Kirill
11.08.2018
04:19:16
Доброе утро, правильно я понимаю, что после INSERT батча в MergeTree движках новые данные для SELECT будут доступны сразу после завершения INSERT. Но если я хочу использовать специфику типа Summing/Collapsing/Replacing то мне нужно чтоб случился merge либо ипользовать FINAL ?
Для всех движков после INSERT данные будут доступны сразу, для Summing нужно всегда делать агрегацию. Движки в фоне, в зависимости от специфики, при мержах разным спосоом куски обрабатывают.

Aleksandr
11.08.2018
05:46:17
Привет. Подскажите пожалуйста, использую движок ReplacingMergeTree делаю count получаю 1.7млн записей делаю count с final получаю 580к записей, делаю optimize table но записи все равно не чистятся и результаты получаю такие же самые, в чем может быть причина? Ключ версии выбрал поле типа DateTime

Aleksandr
11.08.2018
06:23:19
Спасибо, попробую

Alexey
11.08.2018
06:59:42
Подскажите, какой Engine использовать для следующего кейса: постоянно создаются и меняются новые объекты (до 100 000 в сек) для разных пользователей, объект может быть в 3 состояниях - Started -> InProgress -> Completed (иногда Started->Completed), нужно считать количество объектов в каждом состоянии по каждому пользователю и выдавать их список за какой-то диапазон времени. Изменение состояния большинства объектов происходит в течние минуты. Финальное состояние хотелось бы видеть сразу в SELECT, а не после непредсказуемого merge. Первое, что приходит в голову, - вставлять запись о каждом состоянии в MergeTree (но непонятно, как выбирать только последний стейт каждого объекта) или ReplacingMT и делать SELECT FINAL (но, по тому, что я читал, скорость выборки падает в разы), а так же делать AggregatedMT MV для каждого состояния, чтоб считать объекты в каждом состоянии. Есть какие-то best practice для подобной задачи в КХ?

Aleksandr
11.08.2018
07:01:07
MergeTree

Например так: 2 поля start / complete 0 / 0 - start 1 / 0 - in progress 1 / 1 - complete

Всегда можно узнать состояние

Slach
11.08.2018
07:02:17
MergeTree
Он уже поддерживает update?

Aleksandr
11.08.2018
07:02:31
Ну или просто progress поле с 3 состояниями

И типом UInt8

Update на сколько я знаю только начинают вводить в кодовую базу

Slach
11.08.2018
07:03:22
Как из него последнее состояние выбрать?

Aleksandr
11.08.2018
07:04:09
Where progress=3 если 1 поле И Where start =1 and complete =1

Slach
11.08.2018
07:04:25
Last_value partition by насколько я знаю нет

Это не последнее состояние

Aleksandr
11.08.2018
07:04:54
Последнее состояние чего?

Google
Slach
11.08.2018
07:05:08
Объекта

Финальное состояние человек хочет в select

Aleksandr
11.08.2018
07:05:33
Update это по сути select with change 1 field

На данный момент

Ну

select count(*) from table where start =1 and complete=1

Саша
11.08.2018
07:06:15
argMax не подходит ?

Aleksandr
11.08.2018
07:06:29
Если делать с 1 поле то подходит

Если ввести поле progress с 3 состояниями

Slach
11.08.2018
07:07:09
Ок :) все теперь и я знаю про argmax

Aleksandr
11.08.2018
07:07:20
0 - start 1 - in progress 2 - complete

В любой момент времени можно узнать когда и сколько и каких было состояний

Alexey
11.08.2018
07:08:42
спасибо, а как выбрать список объектов с последними состоянями до того как мердж не прошел?

Aleksandr
11.08.2018
07:09:38
А он и не пройдет

При MergeTree у вас остаются все 3 записи

Это более надёжно для вашей задачи

Alexey
11.08.2018
07:10:13
то есть делать клиентскую обработку?

Aleksandr
11.08.2018
07:10:42
Да

Тогда вы не потеряете свои данные

А старые всегда можно сделать detach

Google
Aleksandr
11.08.2018
07:11:13
И куда то сложить

Alexey
11.08.2018
07:11:14
фактически на 100 записей мне приедет 300 состояний, я перед дальнейшей обработкой откидываю 200?

Billiardball
11.08.2018
07:13:47
MergeTree objectKey | state | userId | date select count(), state, userId from table where date between .... and ... group by state, userId order by date desc limit 1 by objectKey, state, userId

Alexey
11.08.2018
07:22:41
а state надо в PK включать? или достаточно user-id?

Billiardball
11.08.2018
07:24:34
Как хотите) Я бы objectKey и userId ток в пк добавил)

Alexey
11.08.2018
07:25:25
спасибо, буду пробовать на реальных данных

Dmitry
11.08.2018
07:25:28
а state надо в PK включать? или достаточно user-id?
В этом кейсе лишним не будет. Причем лучше date, state, user-id

Denis
11.08.2018
11:10:17
Подскажите, какой Engine использовать для следующего кейса: постоянно создаются и меняются новые объекты (до 100 000 в сек) для разных пользователей, объект может быть в 3 состояниях - Started -> InProgress -> Completed (иногда Started->Completed), нужно считать количество объектов в каждом состоянии по каждому пользователю и выдавать их список за какой-то диапазон времени. Изменение состояния большинства объектов происходит в течние минуты. Финальное состояние хотелось бы видеть сразу в SELECT, а не после непредсказуемого merge. Первое, что приходит в голову, - вставлять запись о каждом состоянии в MergeTree (но непонятно, как выбирать только последний стейт каждого объекта) или ReplacingMT и делать SELECT FINAL (но, по тому, что я читал, скорость выборки падает в разы), а так же делать AggregatedMT MV для каждого состояния, чтоб считать объекты в каждом состоянии. Есть какие-то best practice для подобной задачи в КХ?
Если это игра и результаты запроса нужны не для анализа постфактум, а для хода игры, то не полетит, кх eventual consistent и время выполнения запросов непредсказуемо и слишком медленно для маленьких выборок.

Alexey
11.08.2018
15:06:22
И доп фильтры по завершенным/незавершенным

Большого кол-ва SELECT быть не должно

@den_crane правильно я понимаю, если у меня несколько реплик данных и SELECT будут приходить на разные машины, то это повысит SELECT request rate?

@count0ru я нашел случайно на гитхабе твою репу с КХ под кубер, хотел поинтересоваться, взлетело?

Denis
11.08.2018
16:38:56
Ну да, можно больше запросов делать. И можно тяжёлые запросы выполнять сразу двумя репликами, но это не всегда помогает и ускоряет не кратно числу реплик.

Alexey
11.08.2018
16:43:44
Ну да, можно больше запросов делать. И можно тяжёлые запросы выполнять сразу двумя репликами, но это не всегда помогает и ускоряет не кратно числу реплик.
про фразу "кх eventual consistent и время выполнения запросов непредсказуемо и слишком медленно для маленьких выборок." - правильно, я понимаю, что это by design, то есть он не держит большое количество SELECT в принципе (условно говоря 1-3 в секунду - ок), но так как данные после INSERT доступны сразу для SELECT (как написали выше), то с этой точки зрения он консистентен?

Страница 618 из 723