首页 文章

为基于事件的分析设计数据库模式

提问于
浏览
11

我正在试图找出为我正在编写的基于事件的分析系统建模模型的最佳方法 . 我主要担心的是以一种简单快速的查询方式编写本文 . 我也将使用MySQL . 我将回顾一些要求,并提出一个可能(但我认为很差)架构的概述 .

要求

  • 跟踪事件(例如,“APP_LAUNCH”事件的跟踪发生)

  • 定义自定义事件

  • 能够对> 1个自定义属性上的事件进行分段(例如,在“APP_VERSION”属性上分段出现“APP_LAUNCH”)

  • 跟踪会话

  • 根据时间戳范围执行查询

可能的建模

我遇到的主要问题是如何建模分段和执行查询以获取事件的总体计数 .

我最初的想法是定义一个EVENTS表,其中包含id,int count,timestamp,property(?)和EVENTTYPE的外键 . EVENTTYPE具有属于通用事件类型的id,名称和附加信息 .

例如,“APP_LAUNCH”事件在EVENTS表中将有一个条目,其中包含唯一的id,count表示事件发生的次数,时间戳(不确定标记的内容),以及属性或属性列表(例如“APP_VERSION”,“COUNTRY”等)和名为“APP_LAUNCH”的EVENTTYPE的外键 .

评论和问题

由于以下原因,我很确定这不是建模的好方法 . 这使得难以进行时间戳范围查询(“时间x和y之间的APP_LAUNCHES数”) . EVENTTYPE表并不真正有用 . 最后,我不确定如何对不同的分段执行查询 . 最后一个是我最担心的 .

我将非常感谢帮助正确建模或帮助我找到有用的资源 .

最后一个问题(可能是愚蠢的):为每个事件插入一行是不是很糟糕?例如,假设我的客户端库对我的API进行以下调用:

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

我如何将其实际存储在表中(这显然与架构设计密切相关)?为这些调用中的每一个调用只插入一行是不是很糟糕,其中可能有很大的数量?我的直觉反应是,我真的对整体聚合计数感兴趣 . 我没有足够的SQL经验来了解这些查询如何执行可能数十万这些条目 . 当我希望客户端实际获得分析时,聚合表或内存缓存是否有助于缓解问题?

我知道这里有很多问题,但我真的很感激任何帮助 . 谢谢!

1 回答

  • 18

    我认为你的大部分担忧都是不必要的 . 接下来提出一个问题:

    1) 最大的问题是自定义属性,每个事件都有所不同 . 为此,您必须使用 EAV (entity-attribute-value) design . 重要的问题是 - 这些属性有哪些类型?如果不止一个 - 例如字符串和整数,然后它更复杂 . 一般有两种类型的设计:

    • 使用一个表和一列来表示所有类型的值 - 并将所有内容转换为字符串(不是可扩展的解决方案)

    • 为每种数据类型都有单独的表(非常可扩展,我会这样做)

    所以,表格看起来像:

    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_LACHCH类型的所有事件,其中APPVERSION> 4且APP_NAME包含“Office” .

    3) EVENTTYPE表可以达到一致性的目的,即您可以:

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

    或者,您可以使用ID作为数字并在EVENTTYPE表中具有事件名称 - 这样可以节省空间并允许轻松地重命名事件,但是您需要在每个查询中加入此表(导致查询速度稍慢) . 取决于节省存储空间的优先级与较低的查询时间/简单性 .

    4) timestamp远程查询在您的设计中实际上非常简单:

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

    5) "Is it bad to insert a row for every event?"

    这完全取决于你!如果您需要每个此类事件的时间戳和/或不同参数,那么您可能每个事件都应该有一行 . 如果存在大量相同类型和参数的事件,您可以执行大多数日志系统所做的事情:聚合发生在一行中的事件 . 如果你有这种直觉,那么这可能是一种方法 .

    6) " I don't have enough experience with SQL to know how these queries perform over possibly hundreds of thousands of these entries"

    将毫无问题地处理数百或数千个此类条目 . 当你达到一个百万,你将不得不考虑更多的效率 .

    7) "Would an aggregate table or a in-memory cache help to alleviate problems when I want the client to actually get the analytics?"

    当然,这也是一种解决方案,如果查询变慢并且您需要快速响应 . 但是,您必须引入一些机制来定期刷新缓存 . 它过于复杂了;也许最好考虑在输入上聚合事件,见5) .

相关问题