每天更新云中 2-30 亿行数据集中的 1 亿行

Posted

技术标签:

【中文标题】每天更新云中 2-30 亿行数据集中的 1 亿行【英文标题】:Update 100 million rows in a 2-3 billion row dataset in the cloud on a daily basis 【发布时间】:2021-10-22 14:58:40 【问题描述】:

这是一个与时间一样古老的故事。该企业希望获取数十亿行(2-30 亿行),将它们从 Oracle 流式传输到云(在我们的例子中为 AWS)。到现在为止还挺好。然后他们想在云端处理它们,在这里仍然可以。

然后他们希望每天更新约 5% 的行子集(称为 1.25 亿行)并再次处理数据。

我并不是说这不合理,我只是不确定解决这个问题的最有效方法。对于某些背景,我是一名高级全栈开发人员,拥有丰富的 AWS 和大型数据集工作经验,但绝不是大数据专家。此外,如今云中的大数据选项如此之多,很难知道从哪里开始。

那么问题来了:

是否有针对此用例构建的产品(最好在 AWS 中)?

由于它是每天进行的,我们需要能够有效(快速)更新所有行,并能够在第二天到来之前完成我们的处理,整个过程重新开始。

这里的关键是更新的效率。像 Glue 这样的东西会分崩离析,因为数据会有太多的分区(即单个表中有大约 50-1 亿个)。

【问题讨论】:

他们是使用 S3 来保存数据还是 Redshift? 还有,为什么说单表有50-1亿个分区? 最后:您是否有足够的带宽每天将 1 亿行移动到 AWS? S3。我想分区的东西有点模棱两可,因为你可以对任何东西进行分区,但考虑到数据的性质,它在逻辑上是以这种方式分组的。无需详细说明,将它们视为具有 26(平均)行一直到 1000 行的客户。您可以按不同的粒度对分区进行分组,尽管它可能有些随意,并且最终不得不更新更多数据,因为更大的分区。请记住,在 Glue 中,更新是整个表或一个或多个分区。 带宽不是问题。 【参考方案1】:

我会关注 Redshift,主要是因为对于大多数人来说,SQL 比 Spark 更熟悉。假设您正在将数据上传到 S3,则 upsert 过程如下所示(全部在单个事务中):

使用COPY 命令将数据从 S3 上的暂存区插入到临时表中。 如果您实际上是在进行更新(而不是追加),请从基表中删除所有行。 将临时表中的行插入到基表中

我会将其实现为 AWS Batch 作业,但如果您使用 Airflow 或类似的协调框架,它也可以工作。对于更新的大小,Lambda 可能会超时。确保将 Redshift 配置为自动清空。

如果他们设置为使用 Glue,我会采取一种使用“版本”数据的方法,以便您始终存储最新的数据。假设一个夜间工作,它看起来像这样(S3 上的文件夹名称是组成的):

    s3://yourbucket/complete/YYYY/MM/D0读取基础数据集 从s3://yourbucket/updates/YYYY/MM/D1阅读当天的更新 结合两个数据集,为每个键值选择最近的行。 将新数据集写入s3://yourbucket/complete/YYYY/MM/D1 根据新数据集进行处理。

在 S3 上使用生命周期规则来修剪旧数据集。

我认为您会发现仅从基础数据集开始并应用完整的更新历史记录太慢了。尤其是因为您每天要更改 5-10% 的行。

而且您绝对不想按主键进行分区,因为 Glue 在处理大量小文件时性能不佳(这在 AWS 文档中进行了讨论,但我找不到链接 atm)。而且,如果您每次运行都更新 5-10% 的数据,那么仅更新那些已更改的文件不会节省太多。

要对数据集进行分区以提高并行性,您可以对主键进行哈希处理,然后使用哈希的某个子集来创建分区(例如,对哈希进行十六进制化并使用前几个十六进制字符作为分区键)。

【讨论】:

【参考方案2】:

@Parsifal 推荐 Redshift 在我的提要中出现。我将支持在这项工作中使用 Redshift 并添加一些其他可能性。

你没有提到如何使用这个数据集。我猜你希望它在 S3 中进行一些合理的分区,但这并不清楚。您希望能够对此数据运行 SQL 分析吗?所以最优解存在一定的不确定性。

首先,Redshift 可能会变得很昂贵,尤其是当它处于闲置状态时。因此,如果您只需要每晚处理数据而不需要其他任何东西,您将希望在不需要时关闭 Redshift。如果您可以使用 Redshift 24/7 的分析能力,那么您将物有所值。

Next Redshift 早餐吃十亿行数据集。它与 S3 有并行连接,因此可以从那里快速读取。然而,它是一个作为集群实现的列式数据仓库,虽然在大多数(几乎所有)操作上都很快,但有些算法在这种架构上不能很好地工作。 (map-reduce 出现是有原因的)因此请确保您需要进行的数据处理将映射到传统数据库。如果您不确定,请寻求帮助。

Redshift Spectrum 是一组功能,允许 Redshift 将 S3 文件作为“外部表”进行操作。这可以大大简化 S3 作为数据存储的使用,但这确实有一些限制 - 您无法从 Redshift 内部修改这些 S3 文件,但您可以将内容更改的新文件写入 S3。使用 S3 作为数据存储可能会有一些数据处理损失(并且在某些情况下会加快速度)。如果这些是一个问题,您可能希望为您的表使用本机 Redshift 存储。它不会为您的处理增加大量复杂性。

Redshift 数据库可以“快照”然后关闭。第二天,您可以从此快照创建一个新的 Redshift 数据库,然后您就可以开始运行了。该数据库通常会在 10 到 20 分钟内可用,因此您可能需要在日常处理中需要它之前先启动它。

我会根据您的情况查看 Redshift,但很多关于您希望如何使用的信息取决于您在此处理步骤之外如何使用数据的因素。

【讨论】:

【参考方案3】:

有多种选择,云很好,您可以尝试看看最适合您的选项,而无需花费大量时间或金钱使用不可行的工具。

这里唯一的评论是操作约 1 亿行,可能值得看看 ETL (AWS Glue) 或创建具有更新值的临时表(Oracle 有 INSERT FROM SELECT,AWS RedShift 有 CREATE TABLE AS SELECT

有一些常用选项和工具可以加载/处理大量数据:

AWS Glue - ETL 和数据目录。这是在加载到另一个数据存储库之前/期间准备数据的好工具 根据您拥有的数据以及“流程数据”的含义,也许 RDS 就足够了。根据我的经验,在 90% 的情况下,对于基本分析和数据操作来说,一个扩展良好的数据库已经足够好了。 AWS RedShift 是一个分析引擎,可以处理 PB 级数据,但它并不真正适合数据操作 AWS EMR - 托管 Spark/Presto/HBase 集群,如果您能正确使用它,它会非常强大 AWS Athena - 托管的无服务器 EMR/Presto 接口,它有一个简单易用的类似 SQL 的接口

注意:

如果您在迁移到 AWS 时压缩数据,请考虑使用 BZIP2,因为格式是“可拆分的”,并且某些工具(athena、glue..)可以使用并行加载大文件 处理来自 S3 的大型数据集,创建私有 s3 链接以限制来自公共端点的过多出口成本

像 Glue 这样的东西会因为数据有太多的分区而分崩离析

很有趣,也许您可​​以直接使用 aws 来处理用例

【讨论】:

以上是关于每天更新云中 2-30 亿行数据集中的 1 亿行的主要内容,如果未能解决你的问题,请参考以下文章

插入select查询的MySql太慢,无法复制1亿行

每天4亿行SQLite订单大数据测试(源码)

每天4亿行SQLite订单大数据测试(源码)

通过 PostgreSQL 数据库聚合大型(数十亿行)数据集

无法理解数十亿行的更新计数 INSERT

Mysql 搜索 1.18 亿行耗时 86 秒