КХ.
Есть таблица для ивентов вида:
(
ID UInt32
Event String
GUID String
Path String
IP UInt32
UserID UInt32
TrackedDate Date
)
GUID — идентификатор юзера в браузере (кука), Event — что произошло (page или image), Path — урл события, UserID — некий параметр для группы.
У меня есть задача — получить все ивенты с Path = %success% с Event = page` для которых есть другой Event = image. собственно это решается достаточно легко:
SELECT *
FROM analytics.EventTrack
WHERE (UserID = 92) AND (Event = 'page') and (Path like '%onepage/success%') AND (TrackedDate >= toDate('2017-09-01')) AND GUID IN (
SELECT GUID
FROM analytics.EventTrack
WHERE (UserID = 92) AND (Event = 'image') AND (TrackedDate >= toDate('2017-09-01'))
)
Есть ситуация, когда пользователь сменил браузер, то есть у него может быть два GUID, но одинаковый IP. В реляционной БД я бы сделал алиас для таблицы и в сабквери бы сверял IP и дату (допустим, не больше суток, потому что динамический айпи, все дела).
Как сделать в КХ, понятия не имею. Были мысли пробовать собирать IP адреса с датами в Memory таблицу (не работал ранее). Но правильно ли это?
У нас сейчас похожая история со списком пользователей имеется. Есть определенная бизнес-логика по которой собирается конечный список пользователей по которым агрегировать данные. Мы собираем список, в TSV файлик и вместе с select запросом на сервер в виде временной таблицы. Работает замечательно.
я бы делал внешний словарь, который содержит текущую проклейку пользователей в виде guid-> id связной компоненты склейки, и отдельным процессом лопатил эти же логи на предмет одинаковых ip или еще какая логика вам в голову придет. словарь потом можно использовать двумя способами, 1. при вставке данных забирать в события текущее состояние склейки 2. при чтении забирать последнее наиболее актуальное состояние. дальше, в вашем запросе "все события1 для которых есть событие2" происходит что-то вроде джойна на себя же по (userid, guid) при этом достаточно произвольное условие на дату, т.е. события могут быть в любом порядке. и любом количестве. может так и должно быть. в любом случае, количество guid со временем неограниченно растет, возможны спецэффекты. дальше, если вы будете шардировать хранение, вам желательно организовать данные так, чтобы объединение результатов на шардах происходило как можно позже, например чтобы джойн был локальным на шарде. это значит что данные должны шардироваться так, чтобы история одного человека попадала в одну машину. это вряд ли получится, если например у вас для guid динамическое объединение в одного человека. это не значит что так не надо делать, просто надо понимать последствия. хотя если у вас id события int32, то возможно вам это не нужно. и ip только v4. в целом задача про последовательности событий в реляцинном случае обычно включает в себя джойн большой таблицы на саму себя по ключу с большой кардинальностью, и нормально не работает. но возможно у вас все не так плохо.
Обсуждают сегодня