Eu tenho uma consulta CTE muito longa que reduzi aqui para facilitar a leitura. Mas ele tenta inserir estado, município, cidade, CEP e rua em suas próprias tabelas e, em seguida, insere seu ID para inserir o endereço na tabela de propriedades.
with tmpstate as (
insert
into
state ....on
conflict ( lower(state_code) ) do
update
set
state_code = excluded.state_code returning id,
state_code ),
tmpcounty as (
insert
into
..... on
conflict ( lower(county),
state_id ) do
update
set
county = excluded.county returning id,
county ),
tmpcity as (
insert
into
.....
values ( 'Sarasota',
(
select
id
from
tmpcounty
limit 1 ),
(
select
id
from
tmpstate
limit 1 ) ) on
conflict ( lower(city),
county_id,
state_id ) do
update
set
city = excluded.city returning id,
city ),
tmpzipcode as (
...... returning id,
zipcode ),
tmpstreet as (
.... ),
tmpproperty as(
insert
into
property (full_address,
street_address,
street_id,
city_id,
state_id,
zipcode_id,
county_id,
property_details )
values('ssss',
'ssss',
(
select
id
from
tmpstreet
limit 1),
(
select
id
from
tmpcity
limit 1),
(
select
id
from
tmpstate
limit 1),
(
select
id
from
tmpzipcode
limit 1),
(
select
id
from
tmpcounty
limit 1),
'{}') returning id)
select
id
from
property
limit 1
Haveria algum ganho de desempenho se eu criasse funções/triggers que inserissem a rua, cidade, etc... e retornassem seus id se existirem ao invés dessa longa consulta CTE?
Executar uma grande instrução com seus CTEs será mais eficiente do que executar várias pequenas.
A única vantagem de ter uma função PL/pgSQL para as inserções individuais é que os planos de instruções são armazenados em cache durante a sessão do banco de dados. Mas você pode colocar sua grande declaração em tal função se quiser fazer uso disso.