【问题标题】:Does (or can) the PostgreSQL `COPY TO` command guarantee a particular row order?PostgreSQL `COPY TO` 命令是否(或可以)保证特定的行顺序?
【发布时间】:2014-08-28 15:26:01
【问题描述】:

我知道 PostgreSQL 9 允许 COPY (SELECT ...) ... 语法,但我需要一个与 PostgreSQL 7 兼容的解决方案。

例如,COPY TO 命令是按照写入表的顺序输出数据,还是使用特定的索引(或主键)?

【问题讨论】:

  • 为什么在地球上你会使用 PostgreSQL 7.anything?从那以后的改进是巨大的,其中一些(例如删除 fsm_pages,或 autovacuum 改进)非常重要。
  • 了解您在此处尝试解决的潜在问题会很有帮助。为什么你需要知道这个/做这个?输出的顺序有什么问题,是什么使它相关?

标签: sql postgresql copy export-to-csv


【解决方案1】:

COPY 从物理表的开头到结尾,逐页线性读取表。

如果表是用COPY 或一系列INSERTs 没有任何UPDATEs 或DELETEs 创建的,那么这将是它的写入顺序——尽管 PostgreSQL 不保证这一点,并且表格的顺序在技术上是未定义的。

如果您需要从古老的 PostgreSQL 生成类似 CSV 的有序输出,我建议使用外部程序(例如 Python + psycopg2 脚​​本)连接并执行 SELECT ... ORDER BY,读取结果,将它们转换为所需的格式,并将它们写入输出文件。

另一个选项,虽然不能保证工作,是在所需的排序键上CLUSTER 原始输入表。这会将表格重写为所需的物理顺序,然后COPY 将在扫描表格时发出。

到目前为止,最好的选择是首先不要使用 PostgreSQL 的史前化石版本。

在 cmets 中解释后编辑

您根本不需要COPY,只是一个效率不高的提取工具/脚本。您可以使用任何现有的 ETL 工具(Pentaho Kettle、Talend Studio、CloverETL 等),或者只是一个简单的脚本。如果您热衷于速度,甚至可以使用 C 语言编写一个简单的 libpq 程序。

这是一个简单的 Python 示例:

#!/usr/bin/env python

import os
import sys
import psycopg2
import csv

csvf = open("csv.out","wb")
csvw = csv.writer(csvf, dialect='excel-tab')

conn = psycopg2.connect("dbname=regress")
curs = conn.cursor()

# Read blocks of 1000 records from the DB
curs.itersize = 1000

curs.execute("SELECT id, name FROM devices ORDER BY id");
csvw.writerow(("id", "name"))
for row in curs:
    csvw.writerow(row)

csvf.close()

当然,它是单线程的、基本的,并且不会自动找出列名,但它给了你想法。如果您想要自动 col 名称,请参阅 psycopg2 dictionary cursors ... 或使用 libpq 或 PgJDBC 等直接提供所有元数据的东西。

libpq 版本可能需要一两个小时的工作时间。

【讨论】:

  • (+1) “到目前为止,最好的选择是首先不要使用 PostgreSQL 的史前化石版本”。同意,但在许多情况下是不可避免的。
  • @user1420752 嗯,如果他们对这种事情很认真,我会完全避开供应商。他们的产品还有哪些不受支持、古老、不安全或损坏的地方?他们会修复自己代码中的错误吗?等等。需要迫使供应商解决此类问题。
  • 我目前为“供应商”工作。现在。也许这就是我应该说的。 ;)
  • @user1420752 呵呵。 “现在”。确实。更严重的是,如果您需要帮助,我会为一个为 PostgreSQL 提供咨询服务的团队工作,包括帮助人们进行应用程序升级。而且我知道 8.3 过渡对很多人来说都很困难。虽然7,不是那么多。无论如何,如果您有兴趣,请查看我的个人资料。否则……祝你好运?
  • @user1420752 你想用这个解决什么潜在的问题?首先,想要订购COPY 似乎是一个奇怪的要求。
【解决方案2】:

我不相信COPY TO 保证任何排序(7.4 文档没有提到任何排序,所以我不会依赖它是一致的——http://www.postgresql.org/docs/7.4/static/sql-copy.html)。很像表上的SELECT没有ORDER BY 子句可能经常按主键顺序输出行,但不能保证。

SELECT 的文档这样说 (http://www.postgresql.org/docs/7.4/static/sql-select.html):

如果指定了 ORDER BY 子句,则返回的行按顺序排序 指定的顺序。如果没有给出 ORDER BY,则返回行 以系统发现最快生产的任何顺序。

我怀疑没有任何SELECTCOPY TO 也差不多。

如果由于向后兼容的需要而无法使用 COPY (SELECT ...) 表单,则 想到的最直接的选择是:

  1. 创建没有索引也没有主键约束destination
  2. 在执行 COPY 之后添加其中一个(在同一事务中)以强制执行所需的排序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多