SQL Practice Logo

SQLPractice Online

MERGE/UPSERT: Performance

Module: Data Modification & Transactions

UPSERT Performance Factors:

1. Index on conflict column (CRITICAL):

Without index: Full table scan to check for conflicts (1,000 rows/sec)

With index: Index lookup to check for conflicts (100,000 rows/sec)

100x speedup with proper index.

Example:

CREATE UNIQUE INDEX idx_users_user_id ON users(user_id);

INSERT INTO users (user_id, username) VALUES (1, 'john')

ON CONFLICT (user_id) DO UPDATE SET username = EXCLUDED.username;

Index enables fast conflict detection.

2. Number of columns updated:

Fewer columns = faster update

More columns = slower update (more data to write)

Fast: DO UPDATE SET status = EXCLUDED.status

Slow: DO UPDATE SET col1 = EXCLUDED.col1, col2 = EXCLUDED.col2, ... (20 columns)

3. Triggers:

No triggers: 100,000 rows/sec

With triggers: 10,000 rows/sec (10x slower)

Triggers fire for both INSERT and UPDATE, adding overhead.

4. Table size:

Small table (< 1M rows): 100,000 rows/sec

Large table (> 100M rows): 50,000 rows/sec

Larger tables have more index overhead.

5. Batch size:

Single row UPSERT: 10,000 rows/sec (network overhead)

Bulk UPSERT (1000 rows): 100,000 rows/sec (10x faster)

Use bulk UPSERT for better performance.

6. Conflict rate:

Low conflict (10% updates): 100,000 rows/sec

High conflict (90% updates): 80,000 rows/sec

Updates are slightly slower than inserts.

UPSERT vs Separate INSERT/UPDATE:

UPSERT:

- Single operation

- Atomic (no race conditions)

- 100,000 rows/sec

- Simple code

Separate INSERT/UPDATE:

- Two operations (try INSERT, catch error, UPDATE)

- Race conditions possible