【问题标题】:Data Store Design for NxN Data AggregationNxN 数据聚合的数据存储设计
【发布时间】:2015-12-22 17:56:28
【问题描述】:

我正在尝试为数据聚合和存储的 NxN 问题提出一个理论解决方案。例如,我有大量通过流传入的数据。流以点为单位发送数据。每个点有 5 个维度:

  1. 位置
  2. 日期
  3. 时间
  4. 姓名
  5. 统计数据

然后需要汇总和存储这些数据,以允许其他用户出现并查询数据的位置和时间。用户应该能够查询如下(伪代码):

显示位置 1,2,3,4,....N 在日期 01/01/2011 和 01/03/2011 之间的上午 11 点和下午 4 点之间的汇总统计信息

不幸的是,由于数据的规模,不可能从动态点聚合所有这些数据,因此需要在此之前进行聚合。如您所见,虽然数据可以聚合在多个维度上。

他们可以查询任意天数或位置,因此查找所有组合需要大量的预聚合:

  • 今天记录位置 1
  • 今天记录位置 1,2
  • 今天记录位置 1,3
  • 今天记录位置 1,2,3
  • 等等...最多N

在查询之前预处理所有这些组合可能会导致大量不可行的处理。如果我们有 200 个不同的位置,那么我们就有 2^200 个组合,这几乎不可能在任何合理的时间内预先计算。

我确实考虑过在 1 维上创建记录,然后可以在请求时即时进行合并,但这也需要大规模的时间。

问题:

  1. 鉴于用户很可能查询所有维度,我应该如何选择正确的维度和/或维度组合?
  2. 是否有任何我可以参考的案例研究、我可以阅读的书籍或您能想到的任何其他有用的东西?

感谢您的宝贵时间。

编辑 1

当我说将数据聚合在一起时,我的意思是结合其他维度的统计信息和名称(维度 4 和 5)。因此,例如,如果我请求位置 1、2、3、4..N 的数据,那么我必须将这 N 个位置的统计信息和名称计数合并在一起,然后再将其提供给用户。

同样,如果我请求日期为 01/01/2015 - 01/12/2015 的数据,那么我必须汇总这些时期之间的所有数据(通过添加汇总名称/统计信息)。

最后,如果我要求 01/01/2015 - 01/12/2015 日期之间的位置 1、2、3、4..N 之间的数据,那么我必须汇总这些日期之间所有这些位置的所有数据。

为了这个例子,假设通过统计数据需要某种嵌套循环并且不能很好地扩展,尤其是在运行中。

【问题讨论】:

    标签: database database-design architecture scale aggregation


    【解决方案1】:

    试试时间序列数据库!

    根据您的描述,您的数据似乎是一个时间序列数据集。 用户在查询时似乎最关心的时间,在选择时间范围后,用户将通过附加条件来细化结果。

    考虑到这一点,我建议您尝试像InfluxDBOpenTSD 这样的时间序列数据库。 例如,Influx 提供了一种查询语言,它能够处理如下查询,这与您想要实现的目标非常接近:

    SELECT count(location) FROM events
    WHERE time > '2013-08-12 22:32:01.232' AND time < '2013-08-13'
    GROUP BY time(10m);
    

    我不确定您所说的 scale 是什么意思,但时间序列 DB 的设计目的是快速处理大量数据点。 我建议在推出自己的解决方案之前一定要试一试!

    【讨论】:

      【解决方案2】:

      非规范化是一种解决关系数据库性能或可伸缩性的方法。
      IMO 有一些新表格来保存汇总数据并将它们用于报告将对您有所帮助。

      我有大量通过流传入的数据。溪流 以点为单位发送数据。

      案例中实现反规范化的方法有多种:

      • 为流式传输中的数据聚合功能添加新的并行端点 级别
      • 调度作业以在 DBMS 级别聚合数据。
      • 使用 DBMS 触发机制(效率较低)

      在理想情况下,当消息到达流式传输级别时,将分派两个包含location, date, time, name, statistics 维度的数据消息副本进行处理,一个用于OLTP(当前应用程序逻辑)第二个将用于@ 987654322@(BI)进程。
      BI 流程将为报告创建非规范化聚合结构。
      我建议按位置、日期组汇总数据记录。

      因此,最终用户将查询不需要大量重新计算的预先处理的数据,存在一些可接受的不准确性。

      我应该如何选择正确的尺寸和/或组合 考虑到用户很可能查询所有维度的维度 尺寸?

      这取决于您的应用程序逻辑。如果可能,将用户限制为可以由用户分配值的预定义查询(例如从 2015 年 1 月 1 日到 2015 年 1 月 12 日的日期)。在更复杂的系统中,可以选择在 BI 仓库上方使用报告生成器。
      我推荐Kimball's The Data Warehouse ETL Toolkit

      【讨论】:

      • 我认为通常denormalization 代表预连接表以避免查询时代价高昂的JOIN,我认为它不适用于这里。我同意 OLTP 应该与 OLAP 分开引擎,这个问题显然是关于 OLAP 的。此外,如果查询涉及按时间过滤,我认为您不能预先聚合“每个位置的数据记录,日期组”。如果我错了,请纠正我。
      • 您对按一天中的时间进行过滤是对的,但是@gimg1 向我们展示的样本会导致日期汇总数据。在任何情况下,都可以从 OLTP 记录中实现按时间数据过滤。 Denormalization 定义可以作为指导。
      【解决方案3】:

      您至少可以将日期和时间减少到一个维度,并根据您的最小粒度预先聚合您的数据,例如1 秒或 1 分钟分辨率。为相同的分辨率缓存和分块传入流可能很有用,例如每秒将总计追加到数据存储区,而不是针对每个点进行更新。

      名称和位置域更改的规模和可能性有多大?他们之间有什么关系吗?您说该位置可能多达 200 个。我在想,如果名称是一个非常小的集合并且不太可能更改,您可以在单个记录中的每个名称列中保存名称计数,从而减少表的规模每单位时间每个位置 1 行。

      【讨论】:

      • 感谢您的回答。它实际上与我在设计文档中所写的相似。 @Mohsen 的答案再次相似,但对某些来源/资源更具描述性,这就是我选择他的答案的原因。
      【解决方案4】:

      你有很多数据。由于您尝试解析的数据量很大,所有方法都将花费大量时间。 我有两种方法可以提供。 第一个是残酷的,你可能想到了:

      id | location | date | time | name | statistics
      0  | blablabl | blab | blbl | blab | blablablab
      1  | blablabl | blab | blbl | blab | blablablab
      ect.
      

      有了这个,你可以很方便的解析和获取元素,它们都在同一个表中,但是解析时间长,表很大。

      我认为第二个更好:

      Multiple tables:
      id | location
      0  | blablabl
      
      id | date
      0  | blab
      
      id | time
      0  | blab
      
      id | name
      0  | blab
      
      id | statistics
      0  | blablablab
      

      有了这个,你可以更快地解析(很多),获取 ID,然后获取所有需要的信息。 它还允许您预先解析所有数据: 您可以让位置按位置排序、按时间排序的时间、按字母排序的名称等,因为我们不关心 ID 是如何混合的: 如果 id 是 1 2 3 或 1 3 2,没有人真正关心,如果您的数据已经在各自的表中解析,您的解析速度会快很多。

      所以,如果你使用我给出的第二种方法:在你收到一个数据点的那一刻,给他的每一列一个ID:

      You receive:
      London 12/12/12 02:23:32 donut verygoodstatsblablabla
      You add the ID to each part of this and go parse them in their respective columns:
      42 | London ==> goes with London location in the location table
      42 | 12/12/12 ==> goes with 12/12/12 dates in the date table
      42 | ...
      

      有了这个,你想获取所有的伦敦数据,它们都是并排的,你只需要获取所有的 id,并获取其他数据。如果你想取 11/11/11 和 12/12/12 之间的所有数据,它们都是并排的,你只需要取 ids 等..

      希望对我有所帮助,抱歉我的英语不好。

      【讨论】:

        【解决方案5】:

        你应该看看 Apache Flume 和 Hadoop http://hortonworks.com/hadoop/flume/#tutorials

        flume 代理可用于捕获数据并将其聚合到 HDFS 中,您可以根据需要对其进行扩展。一旦它在 HDFS 中,就有许多选项可以可视化,甚至可以使用 map reduce 或弹性搜索来查看您在提供的示例中寻找的数据集。

        【讨论】:

          【解决方案6】:

          我曾使用过一个包含十万种产品和一万家商店的销售点数据库(通常是周级聚合销售,但也有用于购物篮分析、交叉销售等的收据级资料)。我建议你看看这些:

          • Amazon Redshift,高度可扩展,上手相对简单,经济高效
          • Microsoft Columnstore Indexes,压缩数据,拥有熟悉的 SQL 接口,相当昂贵(AWS 的 1 年预留实例 r3.2xlarge 约为 37.000 美元),没有关于如何在集群内扩展的经验
          • ElasticSearch 是我个人最喜欢的,高度可扩展,通过倒排索引进行非常高效的搜索,很好 aggregation framework,没有许可费,有自己的查询语言,但简单的查询很容易表达

          在我的实验中,在相同的硬件上,ElasticSearch 比 Microsoft 的列存储或用于中小型查询的聚集索引表快 20 - 50%。要获得快速响应时间,您必须有足够的 RAM 以在内存中加载必要的数据结构。

          我知道我缺少许多其他数据库引擎和平台,但我最熟悉这些。我也使用过 Apache Spark,但不是在数据聚合上下文中,而是用于分布式数学模型训练。

          【讨论】:

            【解决方案7】:

            真的有一种方法可以做到这一点,而无需以某种方式强制执行吗?

            我只熟悉关系数据库,我认为解决这个问题的唯一真正方法是使用之前建议的平面表,即将所有数据点作为单个表中的字段。我想您只需要决定如何执行此操作以及如何优化它。

            除非你必须保持 100% 到单条记录的准确率,那么我认为真正需要的问题是,我们可以扔掉什么。

            我认为我的方法是:

            1. 计算出最小的时间片段是多少,并在此基础上量化时间域。例如每条可分析的记录时长为 15 分钟。
            2. 在原始记录进入时将它们一起收集到原始表中,但随着量化窗口的过去,将行汇总到分析表中(针对 15 分钟窗口)。
            3. 可以通过时间敏感度较低的例程删除旧的原始记录。
            4. 位置看起来像一个受限集,因此请使用表格将它们转换为整数。
            5. 为汇总表中的所有列编制索引。
            6. 运行查询。

            显然,我打赌以这种方式量化时域是可以接受的。您也可以通过按时域查询原始数据来提供交互式向下钻取,但这仍然会很慢。

            希望这会有所帮助。

            标记

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-04-21
              • 1970-01-01
              • 1970-01-01
              • 2011-07-30
              • 2011-03-15
              • 1970-01-01
              • 2017-11-13
              相关资源
              最近更新 更多