【问题标题】:PostgreSQL bulk insert with ActiveRecord使用 ActiveRecord 的 PostgreSQL 批量插入
【发布时间】:2013-06-10 23:10:06
【问题描述】:

我有很多最初来自 MySQL 的记录。我对数据进行了按摩,以便使用 ActiveRecord 将其成功插入 PostgreSQL。这我可以很容易地以行为基础进行插入,即一次一行。这很慢我想做批量插入,但如果任何行包含无效数据,这将失败。无论如何我可以实现批量插入并且只有无效行失败而不是整个批量?

【问题讨论】:

  • MySQL 过于宽容,有一些非空列包含空数据。
  • 哇。 MySQL实际上允许你这样做吗?这是彻头彻尾的邪恶。

标签: postgresql activerecord


【解决方案1】:

复制

当使用 SQL COPY 进行批量插入(或在 psql 客户端中等效的 \copy)时,不能选择失败。 COPY 不能跳过非法行。您必须将输入格式与您导入的表相匹配。

如果数据本身(而不是装饰器)违反了您的表定义,有办法让这种情况更宽容。例如:创建一个包含所有类型为text 的列的临时登台表。复制到它,然后在转换为实际数据类型并插入实际目标表之前使用 SQL 命令修复违规行。

考虑这个相关的答案:
How to bulk insert only new rows in PostreSQL

或者这个更高级的案例:
"ERROR: extra data after last expected column" when using PostgreSQL COPY

如果 NULL 值 有问题,请暂时从目标表中删除 NOT NULL 约束。在 COPY 之后修复行,然后恢复约束。或者,如果您暂时无法软化您的规则,请使用临时表的路线。
示例代码:

ALTER TABLE tbl ALTER COLUMN col DROP NOT NULL;
COPY ...
-- repair, like ..
-- UPDATE tbl SET col = 0 WHERE col IS NULL;
ALTER TABLE tbl ALTER COLUMN col SET NOT NULL;

或者你只是修复源表。 COPY 告诉您违规行的编号。使用您喜欢的编辑器并修复它,然后重试。我喜欢使用vim。

INSERT

对于 INSERT(如已评论),检查 NULL 值很简单:

要跳过具有NULL 值的行:

INSERT INTO (col1, ...
SELECT col1, ...
WHERE col1 IS NOT NULL

插入某事。 else 而不是 NULL 值(在我的示例中为空字符串):

INSERT INTO (col1, ...
SELECT COALESCE(col1, ''),  ...

【讨论】:

  • 抱歉回复晚了。我没有使用复制,而是使用具有多个值的插入。也使用 activerecord-activejdbc。
  • @zulq:我为INSERT 添加了解决方案。请注意,COPY 在行数较多时快得多。
  • 我没有插入 (col1,...) 选择。我只使用 insert into tablename(col,col2,col...) VALUES(set of values),(another set of values),(another set of values) etc.
【解决方案2】:

对此的常见解决方法是将数据导入TEMPORARY 或UNLOGGED 表,没有约束,并且输入中的数据足够虚假,text 类型列。

然后,您可以对数据执行INSERT INTO ... SELECT 查询,以使用在导入期间清理数据的大查询填充真实表。为此,您可以使用很多 CASE 语句。这个想法是一次性转换数据。

您可以在读取数据时在 Ruby 中进行许多修复,然后使用 COPY ... FROM STDIN 将数据推送到 PostgreSQL。这可以通过 Ruby 的 Pg gem 实现,参见例如 https://bitbucket.org/ged/ruby-pg/src/tip/sample/copyfrom.rb。

对于更复杂的情况,请查看 Pentaho Kettle 或 Talend Studio ETL 工具。

【讨论】:

  • 如果 Postgres 有类似 Oracle 的 LOG ERRORS INTO... 子句的东西会很酷
  • @a_horse_with_no_name 是的,它会的。由于 Pg 内部的工作方式,每行都需要SAVEPOINT,从性能的角度来看,这将是非常可怕的,而且这将是实现 xid 环绕的好方法预防真空非常着急。虽然如果你禁止 AFTER 触发器它可能会工作......
猜你喜欢
  • 2017-01-28
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 2012-08-07
相关资源
最近更新 更多