Postgres 15 Merge Command with Examples
crunchydata.com
crunchydata.com
I really hope `RETURNING` support gets added to `MERGE` asap though (I believe it's been noted as a fairly trivial addition to come in future), then it'll be super powerful for doing bulk upserts that require post-processing.
> Now, MERGE can be used instead!
No mention of deadlocks in the article has me worried about thoroughness of the analysis.
In the Postgres community, MERGE has been talked about for a long time, but in my understanding, part of the reason why the Postgres team initially shipped INSERT ... ON CONFLICT (instead of straight up MERGE) is that it lets you have guarantees about the outcome of the statement (i.e. either INSERT or UPDATE, by use of speculative insertion handling), vs MERGE can cause unique constraint violations and other issues.
AFAIK, the generic syntax of MERGE does not allow for stricter guarantees, and therefore there will always be cases where one is better than the other.
My biggest gripe with ON CONFLICT upserts are the IDs (sequences) having gaps in them. Any good ways to prevent that?
Why do you even need that?
I've worked on various database solutions, both rdbms and analytical and I find sequences to be one of the most misunderstood features in the industry. The only guarantee they make is that they generate unique values. Some of the newer distributed rdbms don't even guarantee they'll be monotonic.
Relying on them generating consecutive values is a sure way to get vendor lock-in to whatever database has made that guarantee.
It 'violates' the principle of least surprise. Intuitively you'd expect `ON CONFLICT .... DO NOTHING` to do nothing, but it will increment the PK every time.
By the time we reached a few thousand entries, we had primary keys in the millions. I personally don't care that there are gaps in the sequence, but gaps of hundreds of thousands definitely leaves a lot to he desired. I think you can circumvent this behaviour by changing from `DO NOTHING` to `DO UPDATE` and doing a dummy write, but that too leaves much to be desired.
I also discovered that `ON CONFLICT` doesn't really work with a high number of concurrent writes. We had to implement our own upsert logic using advisory locks.
-- Will leave gaps
INSERT INTO t (val) VALUES ('abc'), ('def') ON CONFLICT DO NOTHING;
-- Won't leave gaps
INSERT INTO t (val)
SELECT * FROM (VALUES ('abc'), ('def')) AS tmp (val)
WHERE NOT EXISTS (SELECT 1 FROM t WHERE t.val = tmp.val);
https://www.db-fiddle.com/f/6s4uYA987owJxu3CEvfu8t/0Thanks for sharing.
In any bigger project it's just noise and IDs are not helpful information anyway, not even at a glance. It's better to just ignore them, use bigint and move on.
Perhaps because people working for free can decide what they want to work on?
I think merge is cool, but it also easily replicated with what most of us do now for upserts in postgres using ON CONFLICT.
I don’t think that is an accurate characterisation of the Postgres core team
https://www.mssqltips.com/sqlservertip/3074/use-caution-with...