I wonder why there is a difference in execution plan cost for the 2 queries :
create table test_insert(id int not null primary key, value varchar2(10));
--1
insert into test_insert(id,value)
values (2,'111');
--2
insert into test_insert(id,value)
select 3,'111' from dual where not exists (select null from test_insert where id =3);
Cost for query 2 is always higher (how much depends on number of rows in the table).
In my understanding not exits ...
should not add any overhead - in order to enforce PK constraint the engine must check the corresponding unique index anyway, so subquery adds extra parsing time, but not execution time or extra step to the plan.
The example is for Oracle, but I checked Postgres as well, results are similar.
For example,
--1
| Id | Operation | Name | Cost |
--------------------------------------------------------
| 0 | INSERT STATEMENT | | 1 |
| 1 | LOAD TABLE CONVENTIONAL | TEST_INSERT | |
--------------------------------------------------------
--2
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | | | 3 (100)| |
| 1 | LOAD TABLE CONVENTIONAL | TEST_INSERT | | | | |
|* 2 | FILTER | | | | | |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | SYS_C0012345 | 1 | 13 | 1 (0)| 00:00:01 |