PostgreSQL COPY 管道输出到 gzip,然后到 STDOUT
PostgreSQL COPY pipe output to gzip and then to STDOUT
以下命令运行良好
$ psql -c "copy (select * from foo limit 3) to stdout csv header"
# output
column1,column2
val1,val2
val3,val4
val5,val6
但是以下情况不会:
$ psql -c "copy (select * from foo limit 3) to program 'gzip -f --stdout' csv header"
# output
COPY 3
为什么这个命令的输出是 COPY 3
?我希望在通过 gzip
.
之后,输出将是压缩的 CSV 字符串
下面的命令有效,例如:
$ psql -c "copy (select * from foo limit 3) to stdout csv header" | gzip -f -c
# output (this garbage is just the compressed string and is as expected)
߉T`M�A �0 ᆬ}6�BL�I+�^E�gv�ijAp���qH�1����� FfВ�,Д���}������+��
如何制作单个 SQL 命令,直接 将结果通过管道传输到 gzip
并将压缩字符串发送到 STDOUT
?
您可以使用复制到程序:
COPY foo_table to PROGRAM 'gzip > /tmp/foo_table.csv' delimiters',' CSV HEADER;
副本是 运行在服务器上使用 gzip,而不是将 STDOUT 从 gzip 转发到客户端。
您可以改用 \copy,这将 运行 在客户端进行 gzip:
psql -q -c "\copy (select * from foo limit 3) to program 'gzip -f --stdout' csv header"
这与您在问题中显示的 gzip 管道基本相同。
当您使用 COPY ... TO PROGRAM
时,PostgreSQL 服务器进程(后端)启动一个新进程并将文件通过管道传输到进程的标准输入。该过程的标准输出丢失。如果被调用程序将数据写入文件或类似文件,则使用 COPY ... TO PROGRAM
才有意义。
如果您的目标是压缩通过网络传输的数据,您可以在连接字符串中使用 sslmode=require sslcompression=on
来使用 SSL network compression feature I built into PostgreSQL 9.2。不幸的是,这已被弃用,大多数 OpenSSL 二进制文件都禁用了该功能。
目前有一个本地网络压缩 patch under development,但是否会生成 v14 值得怀疑。
除此之外,您暂时得不到您想要的
如果目标是压缩副本的输出以使其通过网络传输得更快,那么...
psql "postgresql://ip:port/dbname?sslmode=require&sslcompression=1"
如果启用它应该显示“压缩活动”。不过,这可能需要启用一些服务器配置变量。
或者您可以简单地使用 ssh:
ssh user@dbserver "psql -c \"copy (select * from foo limit 3) to stdout csv header\" | gzip -f -c" >localfile.csv.gz
但是...当然,您需要通过 ssh 访问数据库服务器。
如果您没有连接到数据库服务器的 ssh,也许您可以通过 ssh 连接到同一数据中心中的另一个机器,该机器具有连接到数据库服务器的快速网络 link,在这种情况下,您可以通过 ssh 连接到它而不是数据库服务器。数据将在该盒子和数据库之间以未压缩的方式传输,在盒子上压缩,并通过 ssh 传输到您的本地机器。这甚至会在数据库服务器上节省 cpu,因为它不会进行压缩。
如果这不起作用,那么,为什么不将 ssh 命令放入“to program”并让服务器通过 ssh 将其发送到您的机器?您必须设置路由器并打开一个端口,但您可以这样做。当然,您必须找到一种方法将密码放在 ssh 命令行中,这通常是一个很大的禁忌,但也许只是一次。或者直接使用 netcat,不需要密码。
此外,如果您想要速度,请使用 zstd 而不是 gzip。
这里有一个 netcat 的例子。我刚刚测试了它,它起作用了。
在 192.168.0.1 的目标机器上:
nc -lp 65001 | zstd -d >file.csv
在另一个终端:
psql -c "copy (select * from foo) to program 'zstd -9 |nc -N 192.168.0.1 65001' csv header" test
注意 netcat 的 -N 选项。
以下命令运行良好
$ psql -c "copy (select * from foo limit 3) to stdout csv header"
# output
column1,column2
val1,val2
val3,val4
val5,val6
但是以下情况不会:
$ psql -c "copy (select * from foo limit 3) to program 'gzip -f --stdout' csv header"
# output
COPY 3
为什么这个命令的输出是 COPY 3
?我希望在通过 gzip
.
下面的命令有效,例如:
$ psql -c "copy (select * from foo limit 3) to stdout csv header" | gzip -f -c
# output (this garbage is just the compressed string and is as expected)
߉T`M�A �0 ᆬ}6�BL�I+�^E�gv�ijAp���qH�1����� FfВ�,Д���}������+��
如何制作单个 SQL 命令,直接 将结果通过管道传输到 gzip
并将压缩字符串发送到 STDOUT
?
您可以使用复制到程序:
COPY foo_table to PROGRAM 'gzip > /tmp/foo_table.csv' delimiters',' CSV HEADER;
副本是 运行在服务器上使用 gzip,而不是将 STDOUT 从 gzip 转发到客户端。
您可以改用 \copy,这将 运行 在客户端进行 gzip:
psql -q -c "\copy (select * from foo limit 3) to program 'gzip -f --stdout' csv header"
这与您在问题中显示的 gzip 管道基本相同。
当您使用 COPY ... TO PROGRAM
时,PostgreSQL 服务器进程(后端)启动一个新进程并将文件通过管道传输到进程的标准输入。该过程的标准输出丢失。如果被调用程序将数据写入文件或类似文件,则使用 COPY ... TO PROGRAM
才有意义。
如果您的目标是压缩通过网络传输的数据,您可以在连接字符串中使用 sslmode=require sslcompression=on
来使用 SSL network compression feature I built into PostgreSQL 9.2。不幸的是,这已被弃用,大多数 OpenSSL 二进制文件都禁用了该功能。
目前有一个本地网络压缩 patch under development,但是否会生成 v14 值得怀疑。
除此之外,您暂时得不到您想要的
如果目标是压缩副本的输出以使其通过网络传输得更快,那么...
psql "postgresql://ip:port/dbname?sslmode=require&sslcompression=1"
如果启用它应该显示“压缩活动”。不过,这可能需要启用一些服务器配置变量。
或者您可以简单地使用 ssh:
ssh user@dbserver "psql -c \"copy (select * from foo limit 3) to stdout csv header\" | gzip -f -c" >localfile.csv.gz
但是...当然,您需要通过 ssh 访问数据库服务器。
如果您没有连接到数据库服务器的 ssh,也许您可以通过 ssh 连接到同一数据中心中的另一个机器,该机器具有连接到数据库服务器的快速网络 link,在这种情况下,您可以通过 ssh 连接到它而不是数据库服务器。数据将在该盒子和数据库之间以未压缩的方式传输,在盒子上压缩,并通过 ssh 传输到您的本地机器。这甚至会在数据库服务器上节省 cpu,因为它不会进行压缩。
如果这不起作用,那么,为什么不将 ssh 命令放入“to program”并让服务器通过 ssh 将其发送到您的机器?您必须设置路由器并打开一个端口,但您可以这样做。当然,您必须找到一种方法将密码放在 ssh 命令行中,这通常是一个很大的禁忌,但也许只是一次。或者直接使用 netcat,不需要密码。
此外,如果您想要速度,请使用 zstd 而不是 gzip。
这里有一个 netcat 的例子。我刚刚测试了它,它起作用了。
在 192.168.0.1 的目标机器上:
nc -lp 65001 | zstd -d >file.csv
在另一个终端:
psql -c "copy (select * from foo) to program 'zstd -9 |nc -N 192.168.0.1 65001' csv header" test
注意 netcat 的 -N 选项。