我正在构建一个应用程序,它将每隔一段时间使用 JSON 获取消息并将这些消息存储在 postgres 数据库中。现在我想防止重复,所以我计算了消息的 sha-512 并将其设置为主键。由于我想防止重复,我可以做两件事:
- 从数据库中获取所有哈希值,并查看何时插入新消息(如果哈希值已存在)(签入代码)
- 使用插入忽略(在 postgres 中可能是更新,因为 postgres 不支持插入忽略)并让数据库处理这些异常
考虑到我可能一次插入几条消息,我想知道方法二是否会查找主键并查看每个插入是否存在,而不是使用方法 1 仅将列表存储在内存中。什么是最高效的?
PostgreSQL 没有,
INSERT ... IGNORE
所以这不是一个选择。您可以使用类似 upsert 的操作(搜索“postgresql upsert”),但它们肯定会降低性能。插入和忽略重复键上产生的错误是可能的,但它往往会导致非常垃圾的日志。就个人而言,我会做有效地做批量 upsert 的事情,我会做这样的事情:
CREATE TEMPORARY TABLE staging_table(...)
COPY TO staging_table(...) FROM ...
(或做批量插入)LOCK TABLE real_table IN EXCLUSIVE MODE
INSERT INTO real_table(...) SELECT col1,col2,col3,... FROM staging_table WHERE NOT EXISTS (SELECT 1 FROM real_table WHERE real_table.primarykey = staging_table.primarykey)
COMMIT
如果需要,您可以在
UPDATE
之前执行操作INSERT
,使用新值更新现有记录。这
LOCK TABLE
对于防止并发更新因错误而失败是必要的。您仍然可以SELECT
在更新期间从表中。如果您有自己
EXPLAIN
的计划,您INSERT
应该会看到JOIN
当您插入大量记录时它已被转换为一个。