防止复制csv postgresql上的重复数据的最佳方法

时间:2015-07-26 16:10:08

标签: postgresql csv postgis

这更像是一个概念性问题,因为我正在计划如何最好地实现我们的目标。

我有一个包含5列的postgresql / postgis表。我将通过copy命令每隔10分钟左右从csv文件插入/附加数据到数据库。可能会有一些重复的数据行,所以我想将数据从csv文件复制到postgresql表,但是防止任何重复的条目从csv文件进入表。有三列,如果它们全部相等,则表示该条目是重复的。它们是“纬度”,“经度”和“时间”。我应该从所有三列制作复合键吗?如果我这样做,它会在尝试将csv文件复制到数据库时抛出错误吗?我将自动复制csv文件,所以我希望它继续并复制不重复的文件的其余部分,而不是复制重复项。有没有办法做到这一点?

此外,我当然希望它以最有效的方式查找重复项。我不需要查看整个表(这将是非常大的)重复...只是通过行上的时间戳过去20分钟左右。我用时间列索引了数据库。

感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

我想我会采取以下方法。

首先,在您关心的三列上创建一个索引:

create unique index idx_bigtable_col1_col2_col3 on bigtable(col1, col2, col3);

然后,使用copy将数据加载到临时表中。最后,你可以这样做:

insert into bigtable(col1, . . . )
    select col1, . . .
    from stagingtable st
    where (col1, col2, col3) not in (select col1, col2, col3 from bigtable);

假设没有其他数据修改,这应该可以实现您想要的。从性能角度来看,使用索引检查重复项应该没问题。

另一种方法是在重复密钥更新"上模拟MySQL"忽略这些记录。 Bill Karwin建议在回答question时实施一条规则。规则的文档是here。使用触发器也可以做类似的事情。

答案 1 :(得分:2)

的Upsert

Answer by Linoff是正确的,但可以简化Postgres 9.5 new ”UPSERT“ feature(a.k.a。MERGE)。该新功能在Postgres中以INSERT ON CONFLICT语法实现。

我们可以让ON CONFLICT子句检测违规,而不是显式检查是否违反了唯一索引。然后我们DO NOTHING,这意味着我们放弃了INSERT的努力,而没有费心去尝试UPDATE。因此,如果我们无法插入,我们只需转到下一行。

我们得到的结果与Linoff的代码相同但却失去了WHERE条款。

INSERT INTO bigtable(col1, … )
    SELECT col1, …
    FROM stagingtable st
ON CONFLICT idx_bigtable_col1_col2_col
DO NOTHING
;

答案 2 :(得分:2)

Basil的方法很棒,但是有轻微的语法错误。我不确定为什么@Bhargav Rao删除了我以前的帖子。通过某种方式参考文档https://www.postgresql.org/docs/9.5/sql-insert.html,我可以使其正常工作。

INSERT INTO bigtable(col1, … )
    SELECT col1, …
    FROM stagingtable st
ON CONFLICT (col1)
DO NOTHING
;