【问题标题】:DB Selection and Modeling Time Series Data with Ad-Hoc queries使用即席查询的数据库选择和建模时间序列数据
【发布时间】:2014-12-17 15:13:01
【问题描述】:

我必须开发一个用于跟踪/监控蜂窝网络性能的系统。

域包含一组分层元素,每个元素都有一组相关的计数器,这些计数器会定期(每 15 分钟)报告一次。系统应收集这些计数器值(以大型 XML 文件的形式提供)并定期在两个维度上聚合它们:时间(从 15 小时到每天)和 层次结构(从低级到高级元素)。聚合通常是一个简单的 SUM,但有时需要平均值/最小值/最大值等。当然,对于元素维度聚合,它需要按层次结构分组(将所有子项分组到一个父记录)。用户应该能够定义和查看 KPI(关键绩效指标)——即各种计数器上的一些计算。 KPI 可能只需要一个元素、多个元素(为每个元素生成一个数据系列)或作为多个元素的聚合(导致聚合数据的一个数据系列)。

系统大约有 10-15 个用户,每小时大概有 20-30 个查询。查询响应时间应该是几秒钟(对于包含许多元素和较长时间段的非常大的报告,最长可达 10-15 秒)。

在高层次上,这是流程:

  1. 解析和输入计数器数据 - 有一组 XML 文件,其中包含元素的计数器数据的定期更新。所有文件的大小约为 4GB / 15 分钟(因此大约 400GB/天)。
  2. 每小时聚合 - 每小时一次,所有收集的计数器,所有元素都应该聚合 - 每 4 条与一个元素相关的记录被聚合成一个每小时记录,应该存储。
  3. 每日汇总 - 每天一次,所有收集的 2 个计数器,所有元素都应汇总 - 与一个元素相关的每 24 条记录汇总为一条每日记录。
  4. 元素聚合 - 对于每个时间维度聚合,可能需要沿元素的层次结构聚合 - 子元素的所有记录都聚合到父元素的一条记录中。
  5. KPI 定义 - 用户应该有某种方式来定义 KPI。 KPI 是基于相同粒度(时间维度)的计数器的计算定义。计算可能(并且将)涉及多个元素级别(例如 p1.counter1 + sum(c1.counter1),其中 p1 是 c1 中一个或多个记录的父级)。
  6. 用户交互 - 用户可以选择一个或多个元素和一个或多个计数器/KPI、要使用的粒度、要查看的时间段以及是否聚合所选数据。

    • 聚合的情况下,结果是一个数据系列,其中包括每个相关时间点的所有选定元素的“相加”值。在“SQL”中:

      选择 p1.time SUM(p1.counter1) / SUM(p1.counter2) * SUM(c1.counter1) FROM p1_hour p1, c1_hour c1 WHERE p1.time > :minTime 和 p1.time

    • 如果没有聚合,需要保留来自 p1 的标识符并为每个选定元素提供一个数据系列

      选择 p1.time, p1.id, SUM(p1.counter1) / SUM(p1.counter2) * SUM(c1.counter1) FROM p1_hour p1, c1_hour c1 WHERE p1.time > :minTime 和 p1.time

系统必须为 15 分钟、小时和每日记录保留 10、100 和 1000 天的数据。以下是一个大小估计,仅考虑 4 字节的整数列,用于存储类型 P 的元素有 400 个计数器,类型 C 的元素有 50 个计数器,类型 GP 的元素有 400 个计数器:

当它加起来时,我假设基于 DDL(实际上,DB 优化存储)为 3.5-4 TB 的数据加上索引可能需要大约 20-30% 的额外数据。对于子“表”,每个表可以获得接近 20 亿条记录。

值得注意的是,随着网络的发展,我会不时添加计数器(可能每 2-3 个月)。

我曾经使用 Oracle 实现了一个非常相似的系统(尽管可能数据较少)。这一次我可能不会使用商业数据库,必须恢复到开源解决方案。此外,随着无 SQL 和专用时间序列数据库的日益普及,也许关系型数据库不是可行的方法?

您将如何处理此类开发?可以使用哪些产品?

通过几天的研究,我想出了以下内容

  • 使用 MySQL / PostGres
  • InfluxDB(或类似产品)
  • Cassandra + Spark
  • 其他?

如何使用每种解决方案以及每种方法的优点/缺点是什么?如果可以,请详细说明或建议支持这种开发的整体(硬件)架构。

欢迎提出意见和建议 - 最好来自有类似项目实践经验的人。

【问题讨论】:

    标签: time-series data-modeling rdbms influxdb


    【解决方案1】:

    使用开源 RDBMS:

    使用 MySQL 或 Postgres

    表结构将是(想象中的 SQL):

    CREATE TABLE LEVEL_GRANULARITY (
        TIMESTAMP DATE,
        PARENT_ID INT,
        ELEMENT_ID INT,
        COUNTER_1 INT
        ...
        COUNTER_N INT
        PRIMARY_KEY (TIMESTAMP, PARENT_ID, ELEMENT_ID)
    )
    

    例如,我们将有 P1_HOUR、GP_HOUR、P_DAY、GP_DAY 等。

    这些表可以按日期进行分区,以缩短查询时间并简化数据管理(可以删除整个分区)。

    为促进快速加载,请使用 DB 提供的加载器 - 这些加载器通常速度更快,并且可以批量插入数据。

    使用 `SELECT ... INTO ...' 查询可以很容易地完成聚合(由于聚合的范围有限,我认为这不会有问题)。

    查询是直接的,因为聚合、分组和连接是内置的。考虑到表有多大,我不确定查询性能。

    由于它是写入密集型的,我认为集群在这里没有帮助。

    优点:

    • 简单的配置(假设没有集群等)。
    • SQL 查询功能 - 灵活

    缺点:

    • 查询性能 - 会起作用吗?
    • 管理开销
    • 刚性架构
    • 缩放?

    【讨论】:

      【解决方案2】:

      使用 InfluxDB(或类似的东西):

      我没有使用过这个数据库,也没有写过一些

      该模型将为每个级别和粒度的每个元素创建一个时间序列。

      数据系列名称将包括元素的标识符和粒度。

      例如P.P_ElementID.G.15MINP.P_ElementID.C.C1_ELEMENT_ID.G.60MIN

      数据系列将包含与该级别相关的所有计数器。

      在插入新数据点之前,输入必须解析 XML 并构建数据系列名称。

      InfluxDB 具有类似 SQL 的查询语言。并允许以类似 SQL 的方式指定计算。它还支持分组。通过使用正则表达式可以按元素分组,例如SELECT counter1/counter2 FROM /^P\.P_ElementID\.C1\..*G\.15MIN/ 获取 ElementID 的所有子代。

      一般来说,有一个按时间分组的概念,它是针对这种数据而设计的。

      优点:

      • 应该很快
      • 支持与 SQL 非常相似的查询等
      • 支持按日期删除(但每个系列都必须这样做...)
      • 灵活的架构

      缺点: * 目前,似乎不太容易支持集群( * 集群 = 更多维护 * 它可以支持数百万个数据系列(并且仍然可以快速运行) * 不太常见,记录较少(目前)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多