Conditional INSERT with ON CONFLICT in PostgreSQL - Time & Space Complexity
We want to understand how the time taken by a conditional INSERT with ON CONFLICT changes as the data grows.
Specifically, how does the database handle inserting or updating rows when conflicts happen?
Analyze the time complexity of the following PostgreSQL query.
INSERT INTO users (id, name, email)
VALUES (1, 'Alice', 'alice@example.com')
ON CONFLICT (id) DO UPDATE
SET name = EXCLUDED.name,
email = EXCLUDED.email;
This query tries to insert a user. If a user with the same id exists, it updates the name and email instead.
Look for repeated work inside the query execution.
- Primary operation: Checking if the id already exists (conflict check) and then inserting or updating.
- How many times: This happens once per row inserted, but the conflict check may scan an index or table to find duplicates.
As the number of rows in the table grows, the time to check for conflicts depends on how fast the database can find the id.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 3 index comparisons |
| 100 | About 7 index comparisons |
| 1000 | About 10 index comparisons |
Pattern observation: The conflict check uses an index, so operations grow slowly, not linearly.
Time Complexity: O(log n)
This means the time to insert or update grows slowly as the table gets bigger, thanks to the index lookup.
[X] Wrong: "The INSERT with ON CONFLICT always takes the same time no matter how big the table is."
[OK] Correct: The database must check for conflicts using an index, which takes more time as the table grows, but this growth is slow (logarithmic), not constant.
Understanding how conditional inserts work and their time complexity helps you explain database efficiency clearly and confidently in real-world situations.
"What if the table had no index on the conflict column? How would the time complexity change?"