将新文件仅从 S3 加载到 Redshift 的简单方法?

Simple way to load new files only into Redshift from S3?

Redshift COPY 命令的文档指定了两种选择要从 S3 加载的文件的方法,您可以提供一个基本路径并加载该路径下的所有文件,或者您指定一个包含要加载的特定文件的清单文件.

但是在我们的案例中,我认为这很常见,S3 存储桶会定期接收包含更新数据的新文件。我们希望能够仅加载尚未加载的文件。

鉴于有一个 table stl_file_scan 记录了所有从 S3 加载的文件,最好能以某种方式排除那些已成功加载的文件。这似乎是一个相当明显的功能,但我在文档或网上找不到任何有关如何执行此操作的信息。

甚至 AWS Data Pipeline 中的 Redshift S3 加载模板似乎也通过将所有数据(新旧数据)加载到分段 table,然后 comparing/upserting 来管理这种情况目标 table。当我们可以从文件名预先知道文件已经加载时,这似乎是一个疯狂的开销。

我知道我们可以将已经加载的文件移出存储桶,但是我们不能那样做,这个存储桶是另一个进程的最终存储位置,而不是我们自己的进程。

我能想到的唯一选择是让其他进程 运行ning 跟踪已成功加载到 redshift 的文件,然后定期将其与 s3 存储桶进行比较以确定差异,并且然后在触发复制过程之前将清单文件写入某处。但多么痛苦啊!我们需要一个单独的 ec2 实例来 运行 有自己的管理和操作开销的进程。

一定有更好的方法!

一般而言,将加载的文件与 S3 文件上的现有文件进行比较是一种不好但可行的做法。常见的 "industrial" 做法是在实际加载数据的数据生产者和数据消费者之间使用消息队列。查看 RabbitMQ 与 Amazon SQS 等。

在这里我想提一下一些步骤,包括如何在 redshift 中加载数据的过程。

  1. 将本地 RDBMS 数据导出到平面文件(确保删除无效 字符,在导出期间应用转义序列)。
  2. 将文件拆分为每个 10-15 MB 以获得最佳性能 上传和最终数据加载。
  3. 将文件压缩为 *.gz 格式,这样您就不会花费 1000 美元 惊喜账单 :) .. 在我的例子中文本文件被压缩 10-20 次。
  4. 列出清单文件的所有文件名,这样当您发出 COPY 命令时 Redshift 将其视为一个负载单元。
  5. 将清单文件上传到 Amazon S3 存储桶。
  6. 将本地 *.gz 个文件上传到 Amazon S3 存储桶。
  7. 使用不同的选项发出 Redshift COPY 命令。
  8. 安排从本地和 AWS 上的 S3 暂存区归档文件。
  9. 捕获错误,设置失败时的重启能力 这样做很简单,你可以按照这个 link.

我就是这样解决问题的,

S3 --(新创建日志上的 Lambda 触发器)-- Lambda -- Firehose -- Redshift

它适用于任何规模。随着负载增加,对 Lambda 的调用次数增加,对 firehose 的数据增加,一切都会自动处理。

如果文件格式有问题,您可以配置死信队列,事件将发送到那里,您可以在修复 lambda 后重新处理。