我有一个用例将选定的数据从 Postgres 移动到 Amazon S3。这应该在一个步骤中发生。我正在编写一个java程序来完成这项工作。
我想出了一种分两步复制数据的方法。我使用 CopyManager 库和 copyOut 方法将数据导入我的本地。在此之后,我使用 Java 将相同的文件移动到 S3 中。
postgres 代码将数据导入我的本地
CopyManager copyManager = new CopyManager((BaseConnection) con);
FileWriter fileWriter = new FileWriter("file.csv");
copyManager.copyOut("COPY (SELECT stmt) TO STDOUT WITH DELIMITER '\t' CSV HEADER", fileWriter);
从本地移动到 S3 的 AWS 代码
AmazonS3 conn = new AmazonS3Client(credentials);
conn.setEndpoint("xxx.com");
conn.putObject(
bucket1.getName(),
"request.json",
new File("file.csv")
);
我希望它一次性发生,而不是写入文件然后将文件移动到 S3。
最佳答案
如果您愿意在 python 中执行此操作,这里有一个应该可以工作的示例:
import boto
import gzip
import psycopg2
import tempfile
# database connection setup
connection = psycopg2.connect('postgresql://scott:tiger@localhost/mydatabase')
connection.autocommit = True
cursor = connection.cursor()
# aws connection setup
s3_connection = boto.connect_s3('<aws access key>', '<aws secret key>')
bucket = s3_connection.get_bucket('<bucket>')
with tempfile.NamedTemporaryFile() as t:
with gzip.GzipFile(t.name, mode='wb') as g:
cursor.copy_expert("COPY ({0}) TO STDOUT WITH CSV HEADER".format('<select_query>'), g)
key = boto.s3.key.Key(bucket, '<s3_key>')
key.set_contents_from_filename(g.name)
这个过程使用了 python 中的
tempfile
模块,它允许你创建一个文件,在过程中使用然后删除。上下文管理器( with tempfile...
)简化了文件写入过程的管理,因此您不必手动删除它。根据您设置临时文件的方式,您可以使系统用户可以访问或从不可见该文件。基本上,您将 SELECT 语句流式传输到 STDOUT,然后将 STDOUT 写入临时文件。在内存管理、速度和访问方面,您仍然对数据库中的 SELECT 语句感到满意。好处是您在尝试将其传输到 S3 时不需要将整个文件保存在内存中;缺点是您需要足够的磁盘空间来临时存储文件,而且显然速度较慢,因为您正在写入磁盘而不是在内存中完成整个操作。
另一件要注意的事情是,我保留了python在上传之前使用gzip压缩文件的步骤。我这样做是为了节省上传空间;如果您要上传包含大量重复数据的表格,这将特别有用。
顺便说一句:在您对 SQL 注入(inject)开放的环境中,您应该 而不是 原样使用它;如果这是您的用例的一部分,则有更好的方法来生成 COPY 命令。
关于java - 一步将数据从 Postgres 数据库复制到 AWS S3,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53887266/