BigQuery - 6年的订单迁移,表/查询设计

时间:2017-07-15 20:20:32

标签: google-bigquery

我正在建立一个Spark工作,将6年的电子商务订单/事件迁移到我们新的BigQuery仓库中,以补充新的流媒体功能。迁移的数据与新数据位于同一模型中,视图将根据需要显示部件。

我们有4个数据集:

数据(原始数据 - 分层JSON) 视图(如原始数据上的DIMS - 通常是平坦但不总是) pre_aggs(例如包含一些密钥汇总调整的原始总计的货币 - 平坦) 报告(如您所愿)

与一些流入和无限制的新实时数据不同,这些历史数据的迁移是批量和有限的(我不必关心自己迟到的事件/水印和重复事件)。我还可以通过 event time(orderPlacedTimestamp)手动分区数据,并保存在正确的日期分区表(后缀?)中。完整的数据大约是BQ压缩的2 GB和200万行,因此视图层中不需要大量但相当复杂的结构。我可以选择将原始和聚合编写为Spark的材料表,所以我们真的希望在最佳实践中实现这一点并优化性能(查询速度更重要,值得花一点额外费用)

我在SQL / Query lambda架构上找到了这个非常好的博客,这是一些灵感,并会尝试做类似的事情。

https://www.linkedin.com/pulse/building-robust-real-time-etl-google-bigquery-lambda-novozhilov

我仍然想知道如何最好地存储/分区这些数据,然后构建基于时间的查询来匹配。每周一周,月度报告可能是最常见的。

我的选择似乎是:

  1. 一个表中的所有内容 - 看起来很简单,没有持续的表管理,但是对于每个查询都意味着全面扫描,而我通常只想从一个时间点回溯一年或两年?

  2. 每个时间段一个表格,例如每年,每月

  3. order_history_2017或order_history_201701

    我们有一个日历查询暗淡,每行都有可以使用上面后缀的键 - 例如20170年1月的201701。

    每月意味着72张表似乎相当多,也许每年更好?

    为了论证,说它的每月表,BQ(标准SQL)中最好的方法是查询包含连续时间轴的表的正确前缀,使用正确的后缀动态构造表名(动态或许?

    例如,我想在2017-01-10和2017-02-10之间查询所有订单(订单有orderPlacedTimestamp) - 这意味着扫描(和联合?)只有order_history_2017-01-10和order_history_2017-02在这种情况下-10表,如下所示做BETWEEN:

    SELECT *
    FROM order_history_201701 UNION ALL
    SELECT *
    FROM order_history_201702
    WHERE order.orderPlacedTimestamp BETWEEN DATE(“2017–01-10”) and DATE(“2017-02-10”)
    

    然后我可能会得到这些历史数据需要与“实时”(流媒体)数据结合的场景 - 包​​含在像lambda设计上的文章一样的视图中。

    1. 我没有想过的选项。
    2. BQ有这么多选择! :)

      无论如何,这是我目前的想法,关于这个主题的任何关于表格设计和优化查询构造的知识都会非常受欢迎。

      谢谢大家!

1 个答案:

答案 0 :(得分:1)

我的建议是认真考虑Partitioned Tables

的原生BigQuery功能

虽然流式传输到分区表有一些limitations您可以在过去的30天内流式传输到分区,相对于当前日期的未来5天),但是加载或查询作业没有这样的限制

相当久以前我考虑过使用此选项来解决按列而不是日期的方法,将一些属于日期的属性映射到'0001-01-01'和'9999-12-31'之间(3,652,058天) - 因此要划分的不同属性值)。 POC在概念上是成功的,但我仍然不喜欢它,尤其是Google团队提出partitioning by date or int column的强烈承诺(至少我感受到的那段时间)  的表。我决定等一下。

同时,要刷新并仔细检查加载或查询到分区表仍然没有分区特定的限制(因为它以某种方式在SO Post中发声) - 我做了快速测试,你可以看到下面的结果

第1步 - 创建分区表 - project.dataset.partitioned_table 我刚刚使用UI。

第2步 - 将查询结果插入表的不同分区

#standardSQL
SELECT 13 AS a

将project.dataset.partitioned_table $ YYYYMMDD作为目的地 (你可以使用DML的INSERT)

我在AC(0001-01-01)和结束时的日期范围内运行了几次? (9999-21-31)

第3步 - 检查结果

#standardSQL
SELECT DATE(_partitiontime) AS partition_, a
FROM `project.dataset.partitioned_table`
ORDER BY a

结果是(记住 - partition_的格式在这里是YYYYMMDD)

partition_      a
----------      --
2017-07-16      1
2017-07-16      2
2017-07-16      3
2017-07-16      4
2017-07-15      5
2017-07-14      6
2010-01-01      7
2001-01-01      8
1001-01-01      9
0001-01-01      10
4001-01-01      11
7001-01-01      12
9999-12-31      13