聚合表与实时分析

Aggregate tables vs real-time analytics

我一直在研究将数据流式传输到实时仪表板的不同方法。我过去做过的一种方法是使用星号 schema/dimension 和事实表。这将是聚合表的实现。例如,仪表盘会包含多个图表,一个是当天的总销售额,每个产品的总销售额,每个制造商的总销售额等等。

但是如果这需要实时呢?如果数据需要流式传输到这些图表并进行实时分析处理怎么办?

我一直在研究 Kinesis 流和 Kafka 等解决方案,但我可能遗漏了一些明显的东西。例如,请考虑以下示例。一家公司运营着一个销售馅饼的网站。该公司有一个后端仪表板,他们在其中跟踪与销售、用户、订单等相关的所有数据和分析。

  1. 自定义通过网站下订单
  2. 关系型 (mysql) 数据库收到这个新订单
  3. 图表和分析数据在后端实时更新,例如当天的总销售额,或用户当年的总销售额。

如果场景是需要流式传输此数据,最好的方法是什么?聚合表似乎是显而易见的,但它似乎是周期性的而不是实时的。 Kinesis/Kafka 感觉它适合这里的某个地方。另一种选择类似于 Redshift,但它非常昂贵,而且可能仍然不是解决问题和扩大规模的最佳方式。

这是一个需要实时更新的图表示例,当有大量行要解析时,仅执行位置聚合 SQL 查询可能会受到影响。

这是大多数架构师的典型权衡。 Amazon Redshift 提供了堪称典范的读取优化,但 AWS 堆栈是有代价的。您可以尝试使用 Cassandra,但它会带来一系列挑战。在分析方面,我 从不 建议进行实时分析,原因如下所述。

Doing analytics at real time is not desired, specially using MySQL

上述解决方案来自隔离事务和分析基础设施。这涉及成本,但将确保您在扩展后不必花时间在家务管理上。 MySQL 是一种基于行的 RDBMS,主要用于存储事务数据。基于行,它优化了写入,即写入几乎是实时的,因此,它在读取方面有所妥协。当我这么说时,我指的是一个典型的分析数据集 运行 成数百万 records/day。如果您的数据集不是那么庞大,您可能仍然能够呈现一个显示交易状态的图表。但是既然你指的是 Kafka,我假设数据集非常大。

A real-time dashboard with visualisations gives a bad customer experience

考虑到以上几点,即使您选择仓库/阅读优化基础设施,您也需要了解可视化的工作原理。如果 100 人同时访问仪表板,将与数据库建立 100 个连接,所有连接都获取相同的数据,将它们放入内存,应用仪表板中定义的计算、参数和过滤器,调整可视化中的细化数据集和然后渲染仪表板。直到此时,仪表板才会冻结。 构造不当的查询、索引的低效使用等会使事情变得更糟。

The above problems will amplify more and more with the increase in your dataset. Good practices to achieve what you need would be:

  1. 几乎实时(延迟 1 小时、30 分钟、15 分钟等)而不是绝对实时系统。这将帮助您创建一个平面文件,其中包含已在内存中获取的数据。您的仪表板将简单地读取此数据,并且在对过滤器等的响应方面将非常快。此外,将避免与数据库的多个连接。
  2. 具有数据结构,database/warehouse 针对读取进行了优化。

如果像这样的 "always up-to-date" 报告(销售、用户、订单等)不需要使用近乎零延迟的流处理进行实时更新,则可能有点矫枉过正,而类似 ROLAP 的方法似乎在 efforts/result.

的意义上更优化

你提到了 Redshift,如果你已经准备好镜像你的数据用于分析目的,唯一的问题是价格,你可以考虑另一个免费的开源替代品,它可以用于处理真实的 OLAP(聚合)查询-time(比如 Yandex ClickHouse,或者在某些情况下可能 MongoDb)。

很大程度上取决于数据集的大小;除非你有真正需要聚合的大数据(数百 GB),否则你可以尝试继续使用 mysql 并使用一些技巧:

  • 使用具有高 IOPS 的单独从属 mysql 服务器进行分析,并仅复制构建报告所需的 table;可能使用另一个 table 引擎,更多 suitable 用于分析查询。专门为这些查询设置索引,如果您只需要获取最近几周的数字,则可以避免 table 全面扫描。
  • 预先计算前几个时期的指标(使用类似物化视图的方法)并按计划(例如,每天)刷新它们,然后将预先计算的聚合与仅上一时期的即时聚合结合起来以无需每次都扫描整个事实即可获得实际的报告数据 table。
  • 使用可以在内存中有效缓存报告数据的数据可视化后端,以防止 SQL 数据库因许多类似查询而过载(如果为 100 个用户显示相同的报告或仪表板 SQL数据库负载将与 1) 相同。顺便说一句,我开发了这样的解决方案(不能在这里推荐它,因为它是商业产品)。

对于这些类型的运营分析use-cases,其中数据的 real-time 性质至关重要,您完全正确,大多数 "traditional" 方法可能非常笨拙,尤其是作为你的数据量增加了。快速概览您的选择:

历史方法 (TLDR– Meh)

直到大约 5 年前,实际的做法看起来像

  1. 设置一个主 OLTP 数据库,该数据库将以原始形式处理数据,并对性能或 ACID 属性提供更严格的保证。通常这是 SQL-esque,即 MySQL,PostgreSQL.
  2. 设置辅助 OLAP 数据库,用于离线(也称为非 user-facing)查询。这也可以是一个 SQL-esque 数据库,但它的模式会截然不同,因为它以丰富的形式存储数据。
  3. 建立一些机制,使这 2 个保持同步。这几乎可以归结为 a) 将您的应用程序更改为始终写入两个数据库并执行必要的数据扩充或 b) 构建一个 stand-alone 应用程序从您的 OLTP 数据库读取,执行必要的转换和扩充并写入到您的 OLAP 数据库
  4. 将您的仪表板插入您的 OLAP 数据库,该数据库将具有针对您需要的查询类型优化的模式和索引。

使用您关于馅饼店的示例,OLTP 数据库将用于存储所有馅饼的购买和参考信息,例如客户 ID、账单信息、送货信息等。相比之下,OLAP 数据库可能只是使用架构

维护 table
purchase_totals(day: Date, weekNumber: int, dayOfWeek: int, year: int, total: float)

虽然 weekNumberdayOfWeekyear 并且在技术上是多余的 它们使您的查询更快! 在这些上使用适当的索引字段,您的仪表板已变成 5 个简单(且快速!)聚合查询,带有分组依据和求和,然后可以在 client-side 上计算差异 week-over-week 或 year-over-year。只要您的仪表板每分钟左右刷新一次,您就可以轻松获得接近 real-time 的数据。

当前方法(TLDR- 好)

最近在计算、数据库技术和数据方面的趋势 science/analytics 导致了对上述过程的改进,即通过替换其中的某些组件。变化包括

  1. 使 OLTP 数据库、OLAP 数据库或两者成为 NoSQL 数据库(Mongo 通常是最受欢迎的)。这里的优点是你有一个更灵活的模式,如果上游发生变化(比如,你开始卖蛋糕而不是馅饼),它不会中断。
  2. 保留 SQL 数据库,但转向云提供商解决方案,如 AWS RDS 或 Google Cloud SQL。这从根本上不会改变架构的任何内容,但会显着减轻您的操作负担。
  3. 在 Kafka 或 AWS Kinesis 等流平台之上使用 hard-to-maintain ETL 管道作为 OLAP 和 OLTP 之间的中间层。
  4. 在计划如何执行 ETL 时使用专用工具进行数据清理和转换
  5. 在 OLAP 数据库之上使用专用的可视化工具(思考 Tableau
  6. 使用 pull-based 方法直接从 OLTP 数据库或应用程序中获取数据,而不是等待数据最终到达您的 OLAP 数据库。这对在线服务很有帮助,因为它实际上既为您提供了您想要的数据,又为您提供了服务正常运行和 运行 正常的确认信息(因为它只是满足了您的数据请求)。 Prometheus 这样的系统现在很流行。