No Postgrsql 13.5 - tenho uma instrução SELECT com um procedimento armazenado como condição na coluna PK (id). Isso acaba sendo muito lento:
select * from xyz where id=myfunction('static-parameter') -- very slow
Mas dividindo em duas afirmações é muito rápido. por exemplo
select myfunction('static-parameter') -- Very fast
==> 123
select * from xyz where id=123; -- very fast
Só posso assumir que o postgres está executando a função para cada linha. Mas por que? E como evitar isso? Aqui está o meu caso real com explicação e análise.
# explain analyze select * from users where id = find_user_by_ip('10.255.0.3');
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Seq Scan on users (cost=0.00..163.66 rows=1 width=113) (actual time=3214.990..4868.484 rows=1 loops=1)
Filter: (id = find_user_by_ip('10.255.0.3'::character varying))
Rows Removed by Filter: 592
Planning Time: 0.074 ms
Execution Time: 4868.502 ms
(5 rows)
# explain analyze select find_user_by_ip('10.255.0.3');
QUERY PLAN
--------------------------------------------------------------------------------------
Result (cost=0.00..0.26 rows=1 width=4) (actual time=29.522..29.522 rows=1 loops=1)
Planning Time: 0.059 ms
Execution Time: 31.159 ms
(3 rows)
# explain analyze select * from users where id = 487;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
Index Scan using users_id_key on users (cost=0.28..8.29 rows=1 width=113) (actual time=0.009..0.011 rows=1 loops=1)
Index Cond: (id = 487)
Planning Time: 0.299 ms
Execution Time: 0.031 ms
(4 rows)
Sua função (não procedimento armazenado, que é diferente no PostgreSQL) provavelmente está marcada como volátil. Você provavelmente deve alterar a função para que ela seja marcada como estável ou imutável (assumindo, é claro, que uma dessas coisas seja verdadeira) e então ela deve usar o índice corretamente.
Usa isto: