Postgres INSERT ON CONFLICT DO UPDATE vs INSERT或UPDATE

时间:2018-02-22 08:45:15

标签: postgresql sql-update sql-insert

我有{3}列的stock_price_alert表。 stock_price_idPRIMARY KEY&也FOREIGN KEY到其他表。表定义如下:

create table stock_price_alert (
    stock_price_id integer references stock_price (id) on delete cascade not null,
    fall_below_alert boolean not null,
    rise_above_alert boolean not null,
    primary key (stock_price_id)
);

我需要:

1)INSERT记录(如果不存在)

-- query 1
INSERT INTO stock_price_alert (stock_price_id, fall_below_alert, rise_above_alert)
VALUES (1, true, false);

2)UPDATE记录(如果存在)

-- query 2
UPDATE stock_price_alert SET
    fall_below_alert = true,
    rise_above_alert = false
WHERE stock_price_id = 1;

首先,我需要在SELECT表上发出stock_price_alert查询,以决定是执行查询(1)还是(2)。

Postgres支持INSERT INTO TABLE .... ON CONFLICT DO UPDATE ...

-- query 3
INSERT INTO stock_price_alert (stock_price_id, fall_below_alert, rise_above_alert)
VALUES (1, true, false)
ON CONFLICT (stock_price_id) DO UPDATE SET
    fall_below_alert = EXCLUDED.fall_below_alert,
    rise_above_alert = EXCLUDED.rise_above_alert;

我可以使用query(3)而不是查询(1)或(2)吗?然后,我不需要在先前和之前发出SELECT查询它有助于简化代码。

但我想知道,这是最好的做法?查询(3)会导致性能问题或不必要的副作用吗?感谢。

2 个答案:

答案 0 :(得分:6)

查询3是" UPSERT"的Postgres语法。 (=更新或插入),在Postgres 9.5中引入。

来自documentation

  

ON CONFLICT DO UPDATE保证原子INSERTUPDATE结果;   如果没有独立错误,那么这两个结果之一就是   即使在高并发性下也能保证。这也称为UPSERT -   “UPDATEINSERT”。

这是您想要实现的目标的最佳实践。

答案 1 :(得分:1)

我注意到/测试了INSERTS(尚未测试UPSERTS)使用ON CONFLICT之外还使用WHERE NOT EXISTS的速度要快得多。通常比仅允许ON CONFLICT处理存在检查快大约3倍。我认为这可能会延续到UPSERTS中,从而可能更快地执行INSERT然后执行UPDATE。这是我仅对插入件的测试...

nil