我有 2 个类似的功能,不同的方式导致性能差异很大。
PostgreSQL 版本:9.2.1。
功能 1
create or replace function func_1() returns text as
$$
declare
v_i integer;
v_md5 varchar;
begin
for v_i in 1..1000000 loop
v_md5:='a'|| v_i::character varying;
end loop;
return 'ok';
end;
$$
language plpgsql;
功能二
create or replace function func_select() returns text as
$$
declare
v_i integer;
v_md5 varchar;
begin
for v_i in 1..1000000 loop
select 'a'|| v_i::character varying into v_md5;
end loop;
return 'ok';
end;
$$
language plpgsql;
功能时序
francs=> \timing
Timing is on.
francs=> select func_1();
func_1
--------
ok
(1 row)
Time: 1467.231 ms
francs=> select func_1();
func_1
--------
ok
(1 row)
Time: 1383.424 ms
francs=> select func_select();
func_select
-------------
ok
(1 row)
Time: 22176.600 ms
francs=> select func_select();
func_select
-------------
ok
(1 row)
Time: 23265.755 ms
从上面看,functionfunc_1()
只需要大约1383 ms,但是 functionfunc_select()
大约需要 23265 ms,有人可以解释一下吗?
在第二个循环中使用纯 SQL 语句使数据库引擎在每次循环迭代中编译整体,然后再对其进行评估,而变量赋值一次就很容易解析为低级指令。
select 'a'|| v_i::character varying into v_md5;
为了获得最佳性能,您可能会使用
generate_series
as在我的测试中,它花费了你第一次实现时间的1/6。
附录: 顺便说一句,这三种实现之间的主要区别在于您在一条指令中将多少工作委托给了后端。在我的解决方案中你没有循环,所以它是一条指令,而在你的第二个实现中你有一个包含选择的循环(这是一个复杂的函数),而在你的第一个例子中你有一个包含赋值的循环(即是一个简单的函数)。这解释了差异。