Thi*_*yão 5 postgresql performance functions postgresql-12 query-performance
这很快(49ms):
v_cpf_numerico := ext.uf_converte_numerico(new.nr_cpf);
select cd_cliente into v_cd_cliente
from central.cliente where nr_cpf_cnpj = v_cpf_numerico;
Run Code Online (Sandbox Code Playgroud)
这很慢(15 秒):
select cd_cliente into v_cd_cliente
from central.cliente where nr_cpf_cnpj = ext.uf_converte_numerico(new.nr_cpf);
Run Code Online (Sandbox Code Playgroud)
功能:
create or replace function ext.uf_converte_numerico(_input varchar(30)) returns bigint
as
$$
begin
_input := regexp_replace(_input, '[^0-9]+', '', 'g');
if _input = '' then
return null;
end if;
return cast(_input as bigint);
end
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)
我使用的是 PostgreSQL 12。
为什么第二个变体很慢?
考虑这个简化的等价物:
CREATE OR REPLACE FUNCTION ext.uf_converte_numerico(_input varchar(30))
RETURNS bigint LANGUAGE sql IMMUTABLE PARALLEL SAFE AS
$func$
SELECT NULLIF(regexp_replace(_input, '[^0-9]+', '', 'g'), '')::bigint;
$func$;
Run Code Online (Sandbox Code Playgroud)
PARALLEL SAFE
在 Postgres 10 或更高版本中,因为它是. 如果没有标签,函数默认为PARALLEL RESTRICTED
,这会禁用并行查询。这可能会也可能不会影响显示的查询。但你报告的 15 秒表明你正在大桌子上操作。因此它可以对其他查询产生巨大的影响。
LANGUAGE SQL
启用函数内联,这对于显示的查询(标记后IMMUTABLE
)来说并不重要,但会简化查询计划并提高整体性能。
NULLIF
作为较小的简化。
旁白:您的输入是varchar(30)
,它仍然允许出现超出范围的错误bigint
。要么考虑varchar(18)
确定。或者只是让它text
消除无效的限制。