如何使用基于分区的 INSERT INTO 覆盖 table? - 雅典娜

How to overwrite table using INSERT INTO based on partition? - Athena

我目前正在使用 INSERT INTO Athena 命令通过自动作业更新我的 table 分区 execution_date 每一天。

我现在想通过每天更新 table 两次来配置此作业,但仍按 execution_date 分区。所以我早上的工作 运行 应该像往常一样工作,但是我下午的工作 运行 具有相同的 execution_date 应该覆盖从早上开始也由相同的 execution_date 分区的记录。

我调查了 MSCK REPAIR TABLE,但我不确定它如何适用于我的用例。

如何使用 Athena 的 INSERT INTO 命令覆盖按相同值分区的记录?

Athena 永远不会覆盖数据。如果您想删除或替换数据,您必须自己动手。 INSERT INTOCREATE TABLE AS (CTAS) 将拒绝 运行 如果输出位置有任何东西。

您可以做什么取决于您的要求。最简单的方法是在 运行 您的 INSERT INTO 命令之前删除数据。这样做的缺点是在命令有 运行 之前,分区中将没有数据。 IE。同时查询 运行ning window 将看不到当天的任何数据。您可以确保在重新处理期间没有查询 运行 并避免不一致,但如果这不是一个选项,它会变得更加复杂。

我过去采用的一种替代方法是使用 CTAS 作为转换机制,然后将转换后的数据移动到位。使用新的 UNLOAD feature this becomes a little easier since there is no table created. What you can do is run an UNLOAD command instead of your INSERT INTO and use a temporary output location. If it's the first run of the day you simply copy the files into the right place and create a partition using the Glue Data Catalog API – or even better use partition projection 以避免必须完全处理分区。如果是当天的第二个 运行,您将删除现有分区中的文件并复制新文件到它们的位置。然后删除 UNLOAD 命令输出位置中的所有内容。

当分区中没有数据时和分区中有部分数据时,此替代方案仍然有短暂的 window 时间。在您开始删除旧文件和将所有新文件复制到分区位置之间的任何时间点,查询都可以 运行。 window 最多不应超过几秒钟,特别是如果您并行执行所有删除操作,然后并行执行所有复制操作,但它永远不会为零。

如果您真的想避免不一致,还有另一种选择,即分区位置不必与分区键值相对应。您可以 运行 与以前相同的 UNLOAD 命令,但设置输出位置,以便输出最终与其他分区位于同一位置,但具有唯一的后缀。如果您的 table 按日期分区,并且您的分区具有 s3://example-bucket/data/2021-08-16/s3://example-bucket/data/2021-08-17/ 这样的 URI,您可以将 UNLOAD 命令的输出位置设置为 s3://example-bucket/data/2021-08-17_asdf1234/ 这样的 URI ,其中“asdf1234”是每个 运行 的新随机字符串。转换完成后,您 update the partition's location using the Glue Data Catalog API 指向新位置,但对分区键使用相同的值,例如“2021-08-17”。分区位置更新后,您删除旧位置的文件。这将确保 运行 的任何查询将看到旧数据或新数据,但绝不会没有数据或部分数据。

无法让 Athena 自动替换分区。哪种选择适合您取决于查询在更新期间看不到数据或部分数据的问题有多大。