2013-09-23 2 views
11

Я пытаюсь найти лучший способ моделирования схемы для этой аналитической системы на основе событий, которую я пишу. Моя главная проблема заключается в том, чтобы писать это так, чтобы запросы были простыми и быстрыми. Я тоже буду использовать MySQL. Я рассмотрю некоторые из требований и представляю схему возможной (но я думаю, бедной) схемы.Проектирование схемы базы данных для аналитики на основе событий

Требования

  • Отслеживание событий (например, дорожки вхождения "APP_LAUNCH" событие)

  • Определение пользовательских событий

  • Возможность сегментировать события на> 1 пользовательских свойств (например, прибудет вхождения «APP_LAUNCH», сегментированные по свойству «APP_VERSION»)

  • Трек-сеансы

  • Выполнение запросов на основе диапазона временных меток

Возможное моделирование

Основная проблема, которую я имею, как модель сегментации и запросов, чтобы выполнить, чтобы получить общие подсчеты события ,

Моя первоначальная идея состояла в том, чтобы определить таблицу СОБЫТИЙ с идентификатором, int count, timestamp, свойством (?) И внешним ключом EVENTTYPE. EVENTTYPE имеет идентификатор, имя и дополнительную информацию, относящуюся к родовому типу событий.

Например, событие «APP_LAUNCH» будет иметь запись в таблице СОБЫТИЙ с уникальным идентификатором, числом, представляющим количество раз, когда произошло событие, метку времени (неуверенность в том, что это запечатано), а также свойство или список свойств (например, «APP_VERSION», «COUNTRY» и т. д.) и внешний ключ для EVENTTYPE с именем «APP_LAUNCH».

Комментарии и вопросы

Я довольно уверен, что это не лучший способ смоделировать это по следующим причинам. Это затрудняет выполнение запросов timestamp ranged («Число APP_LAUNCHES между временем x и y»). Таблица EVENTTYPE действительно не служит цели. Наконец, я не уверен, как бы я мог выполнять запросы для разных сегментов. Последний из тех, кого я больше всего беспокоюсь.

Я был бы признателен за помощь в правильном моделировании или указании на ресурсы, которые помогут.

Последний вопрос (который, вероятно, немой): Неправильно ли вставлять строку для каждого события? Так, например, сказать, что мой Клиентская библиотека делает следующий вызов к моему API:

track("APP_LAUNCH", {count: 4, segmentation: {"APP_VERSION": 1.0}}) 

Как бы я на самом деле хранить это в таблице (это тесно связано с проектом схемы, очевидно)? Неправильно ли просто вставлять строку для каждого из этих вызовов, из которых может быть значительная сумма? Моя реакция кишки состоит в том, что меня действительно интересуют главным образом общие агрегированные подсчеты. У меня недостаточно опыта работы с SQL, чтобы знать, как эти запросы выполняют, возможно, сотни тысяч этих записей. Будет ли сводная таблица или кеш в памяти помочь облегчить проблемы, когда я хочу, чтобы клиент фактически получал аналитику?

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

ответ

17

Я думаю, что большая часть ваших проблем не нужна. Возьмем один из ваших вопросов за другим:

1) Самая большая проблема - это настраиваемые атрибуты, разные для каждого события. Для этого вам необходимо использовать EAV (entity-attribute-value) дизайн. Важный вопрос: какие типы могут иметь эти атрибуты? Если более одного - например, string и integer, то это сложнее. Есть вообще два типа такой конструкции:

  • использовать одну таблицу и один столбец для значений всех типов - и конвертировать все в строку (не масштабируемое решение)

  • имеет отдельные таблицы для каждого типа данных типа (очень масштабируемые, я бы на это)

Таким образом, таблица будет выглядеть следующим образом:

Events    EventId int, EventTypeId varchar, TS timestamp 
EventAttrValueInt EventId int, AttrName varchar, Value int 
EventAttrValueChar EventId int, AttrName varchar, Value varchar 

2) Что вы подразумеваете под сегментацией? Запрос различных параметров события? В конструкции EAV упоминалось выше, вы можете сделать это:

select * 
from Events 
    join EventAttrValueInt on Id = EventId and AttrName = 'APPVERSION' and Value > 4 
    join EventAttrValueChar on Id = EventId and AttrName = 'APP_NAME' 
              and Value like "%Office%" 
where EventTypeId = "APP_LAUNCH" 

Это позволит выбрать все события типа APP_LAUNCH где AppVersion является> 4 и APP_NAME содержит «Офис».

3) Таблица типСобытия может служить цели последовательности, то есть вы можете:

table EVENTS (.... EVENTTYPE_ID varchar - foreign key to EVENTTYPE ...) 
table EVENTTYPE (EVENTTYPE_ID varchar) 

Или, вы можете использовать идентификатор как номер и иметь имя события в таблице типСобытия - это экономит пространство и позволяет легко переименовывать события, но вам нужно будет присоединиться к этой таблице в каждом запросе (что приведет к более медленным запросам). Зависит от приоритета сохранения пространства для хранения и уменьшения времени запроса/простоты.

4) метка времени колебались запросы на самом деле очень просты в дизайне:

select * 
from EVENTS 
where EVENTTYPE_ID = "APP_LAUNCH" and TIMESTAMP > '2013-11-1' 

5)"Это плохо, чтобы вставить строку для каждого события?"

Это полностью зависит от вас! Если вам нужна отметка времени и/или разные параметры каждого такого события, то, вероятно, у вас должна быть строка для каждого события. Если существует огромное количество событий одного и того же типа и параметров, вы, вероятно, можете сделать то, что делают большинство систем ведения журналов: агрегировать события, которые происходят в одной строке. Если у вас такое чувство кишки, то это, вероятно, способ пойти.

6)«У меня нет достаточно опыта работы с SQL, чтобы знать, как эти запросы выполнить более возможно, сотни тысяч этих записей»

сотни или тысячи таких записей будет обрабатываться без проблем.Когда вы достигнете milion, вам нужно будет думать гораздо больше об эффективности.

7)«Будет ли совокупная таблица или кэш помощи в памяти, чтобы облегчить проблемы, когда я хочу, чтобы клиент на самом деле получить аналитику?»

Конечно, это также решение, если запросы замедляются, и вам нужно быстро реагировать. Но тогда вы должны ввести некоторый механизм для периодического обновления кеша. Это чрезмерно сложнее; возможно, лучше рассмотреть агрегацию событий на входе, см. 5).

+0

Это фантастический ответ, но у меня есть вопрос. Я немного неясен в отношении вашей точки в № 3. Если EVENTTYPE_ID (имя события) уже существует в таблице СОБЫТИЯ, как возникает последовательность из наличия внешнего ключа в таблице EVENTTYPE? – CCSab

+0

@CCSab, потому что, используя внешний ключ, вы можете обеспечить проверку целостности внутренней базы данных - чтобы можно было ввести только те EVENTTYPE_ID, которые находятся в таблице EVENTTYPE! См. [Ограничения внешнего ключа в руководстве] (http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html) – TMS

+0

О, это делает тонну смысла! Спасибо за фантастический ответ! Я принял его и наградил наградой :) – CCSab

Смежные вопросы