这是在Postgres中批量INSERT ON CONFLICT的正确方法吗?

时间:2017-10-16 14:04:41

标签: postgresql bulkinsert upsert

我将提供一个简单的问题示例。

我有两个表:reviewsusers

reviews更新了一组用户发布的评论。获取评论的过程还会返回提交评论的用户的信息(并且某些用户数据会经常更改)。

每当我使用users批量更新reviews时,我都希望更新COPY。当获取的数据包含来自同一用户的两个或更多评论时,问题出现在users。如果我做一个简单的INSERT ON CONFLICT,我可能会因为INSERT语句无法两次更新同一行而导致错误。

SELECT DISTINCT可以解决这个问题,但我也想保证将最新数据插入users表。这就是我这样做的方式。请记住,我正在批量执行此操作:

1。创建一个临时表,以便我们可以COPY到/来自

CREATE TEMPORARY TABLE users_temp (
    id uuid, 
    stat_1 integer, 
    stat_2 integer, 
    account_age_in_mins integer);

2。 COPY数据放入临时表

COPY users_temp (
    id,
    stat_1,
    stat_2,
    account_age_in_mins) FROM STDIN CSV ENCODING 'utf-8';

第3。锁定users表并执行INSERT ON CONFLICT

LOCK TABLE users in EXCLUSIVE MODE;

INSERT INTO users SELECT DISTINCT ON (1) 
    users_temp.id,
    users_temp.stat_1,
    users_temp.stat_2,
    users_temp.account_age_in_mins
FROM users_temp
ORDER BY 1, 4 DESC, 2, 3
ON CONFLICT (id) DO UPDATE
SET
    stat_1 = EXCLUDED.stat_1,
    stat_2 = EXCLUDED.stat_2,
    account_age_in_mins = EXCLUDED.account_age_in_mins';

我在步骤 3)中执行SELECT DISTINCTORDER BY的原因是因为我:

  1. 只想返回重复行的一个实例。
  2. 从那些 重复确保我获得最新的记录 排序account_age_in_mins
  3. 这是实现目标的正确方法吗?

1 个答案:

答案 0 :(得分:2)

这是一种非常好的方法。 当你只锁定临时表中的元组时,也许你可以避免表锁。 https://dba.stackexchange.com/questions/106121/locking-in-postgres-for-update-insert-combination