我有{3}列的stock_price_alert
表。 stock_price_id
是PRIMARY 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)会导致性能问题或不必要的副作用吗?感谢。
答案 0 :(得分:6)
查询3是" UPSERT"的Postgres语法。 (=更新或插入),在Postgres 9.5中引入。
ON CONFLICT DO UPDATE
保证原子INSERT
或UPDATE
结果; 如果没有独立错误,那么这两个结果之一就是 即使在高并发性下也能保证。这也称为UPSERT
- “UPDATE
或INSERT
”。
这是您想要实现的目标的最佳实践。
答案 1 :(得分:1)
我注意到/测试了INSERTS(尚未测试UPSERTS)使用ON CONFLICT之外还使用WHERE NOT EXISTS的速度要快得多。通常比仅允许ON CONFLICT处理存在检查快大约3倍。我认为这可能会延续到UPSERTS中,从而可能更快地执行INSERT然后执行UPDATE。这是我仅对插入件的测试...
nil