【问题标题】:Suitable Data Model design (RDBMS) for multiple permutations of data适用于多种数据排列的数据模型设计 (RDBMS)
【发布时间】:2014-10-29 12:16:23
【问题描述】:

我正在构建一个分析应用程序,用于跟踪公司营销活动的转化。转换是如果他们去超市购买产品。如果公司是 Heinz,他们可能会针对不同的产品投放广告系列,因此广告系列可能是:

  • 焗豆
  • 番茄汤
  • 番茄酱

这些是在线广告系列,因此它们可以有不同的媒介,例如:

  • 网站
  • Facebook 页面
  • Flash 横幅广告
  • 移动应用广告

如果有人购买产品,则通过超市购买,例如:

  • 沃尔玛
  • 阿斯达
  • 安全通道
  • 克罗格

我们正在跟踪所有这些的转化。分析应用程序需要显示以上任意组合的转化数据。例如,我可能需要显示转​​化...

  • 用于烤豆。
  • 来自 Facebook 页面的烤豆。
  • 适用于沃尔玛超市,但适用于所有广告系列和媒体。
  • 适用于从 Facebook 页面制作的沃尔玛,但适用于所有广告系列。
  • 用于通过 Flash 横幅广告制作的番茄酱和 Safeway。

为了加快分析速度,我们避免处理原始数据(数百万条记录),而是存储每天存储的数据的聚合版本。所以对于 9 月 12 日,我可以存储我们有 12 次烤豆转化,6 次转化(所有产品)是通过网站进行的,沃尔玛有 8 次转化,这些可以放在 3 个单独的表中(称为广告系列,媒体和超市)。但是,如果我需要知道通过 Facebook 页面和沃尔玛进行的番茄酱的转换,那么存储在单独的表格中显然是行不通的。

我正在努力想出一个可以支持上述内容的数据模型。我正在使用标准的关系数据库(MySQL)。也许有更好的策略来处理这个问题。

【问题讨论】:

    标签: database database-design data-modeling rdbms dimensional-modeling


    【解决方案1】:

    是的,有更好的策略。它被称为 Dimensional Modeling,或 Star Schema。

    您存储一个名为事实表的表,其中包含 Campaign、Medium 和 Supermarket 的列。

    对于这些属性中的每一个,事实表中的列是维度表的外键。广告系列、媒介和超市各有一个维度表。

    在您的情况下,为避免数百万行,您可以在事实表中添加第四列 conversions。当您获得转化时增加计数(而不是添加另一行)。

    这是一个示例表:

    CREATE TABLE FactTable (
      campaign_id INT,
      medium_id INT,
      supermarket_id INT,
      conversions INT,
      PRIMARY KEY (campaign_id, medium_id, supermarket_id),
      FOREIGN KEY (campaign_id) REFERENCES Campaigns(campaign_id),
      FOREIGN KEY (medium_id) REFERENCES Mediums(medium_id),
      FOREIGN KEY (supermarket_id) REFERENCES Supermarkets(supermarket_id)
    );
    

    然后就可以查询所有的转化了:

    • 用于烤豆。

      SELECT SUM(conversions) FROM FactTable
      JOIN Campaigns USING (campaign_id) 
      WHERE campaign = 'Baked Beans';
      
    • 来自 Facebook 页面的烤豆。

      SELECT SUM(conversions) FROM FactTable
      JOIN Campaigns USING (campaign_id) 
      JOIN Mediums USING (medium_id)
      WHERE campaign = 'Baked Beans' AND medium = 'Facebook';
      
    • 适用于超市沃尔玛,但适用于所有广告系列和媒体。

      SELECT SUM(conversions) FROM FactTable
      JOIN Supermarkets USING (supermarket_id)
      WHERE supermarket = 'Walmart';
      
    • 适用于从 Facebook 页面制作的沃尔玛,但适用于所有广告系列。

      SELECT SUM(conversions) FROM FactTable
      JOIN Mediums USING (medium_id)
      JOIN Supermarkets USING (supermarket_id)
      WHERE medium = 'Facebook' AND supermarket = 'Walmart';
      
    • 用于通过 Flash 横幅广告制作的番茄酱和用于 Safeway。

      SELECT SUM(conversions) FROM FactTable
      JOIN Campaigns USING (campaign_id)
      JOIN Mediums USING (medium_id)
      JOIN Supermarkets USING (supermarket_id)
      WHERE campaign = 'Ketchup' AND medium = 'Flash Banner Ad' AND supermarket = 'Safeway';
      

    查看books by Ralph Kimball 了解有关维度建模的更多信息。

    【讨论】:

    • 很容易进入我曾经拥有的前 5 个最佳 Stackoverflow 答案!非常感谢:-)
    • 不仅是一个很好的答案,而且说得很好。我只想补充一点,在许多情况下,客户端应用程序在显示名称的控件中嵌入了整数 id(或公共 api 的某种 uuid)。所以不需要连接......只需在 id(s) 上过滤 WHERE 子句。更快。
    • @NaturalData,是的,这是一个很好的优化,我展示了连接,因为它很好地说明了维度表的作用。
    【解决方案2】:

    我认为,通过尝试操纵数据结构来避免处理原始数据,您会增加复杂性并降低灵活性,但实际上并没有什么好处。使用适当的索引和适当调整的查询,查询数百万条记录应该花费很少的时间。我已经在多个字段中查询了包含 50 亿条记录的表,并在 20 毫秒内得到了结果。

    把你的精力放在调优而不是设计新的数据结构上,当使用这些分析的人需要某种稍微不同格式的数据时,你会很感激,这会让你精心策划的设计过时。

    【讨论】:

      猜你喜欢
      • 2013-03-29
      • 2018-02-17
      • 2010-09-23
      • 1970-01-01
      • 2016-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多