Postgresql
不同的查詢導致性能差異很大
我有 2 個類似的功能,不同的方式導致性能差異很大。
PostgreSQL 版本:9.2.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
從上面看,函式
func_1()
只需要大約1383 毫秒,但函式func_select()
大約需要 23265 毫秒,有人能解釋一下嗎?
在第二個循環中使用純 SQL 語句使數據庫引擎在每次循環迭代之前**編譯整個循環,然後對其進行評估,而變數賦值則很容易解析為低級指令一次。
select 'a'|| v_i::character varying into v_md5;
為了獲得最佳性能,您可能會
generate_series
使用create or replace function func_1() returns text as $$ declare v_i integer; v_md5 varchar; begin select 'a'||i into v_md5 from generate_series(1, 1000000) i; return 'ok'; end; $$ language plpgsql;
在我的測試中,它需要你第一次實現時間的1/6 。
附錄: 順便說一句,這三種實現之間的主要區別在於您在一條指令中將多少工作委派給後端。在我的解決方案中,您沒有循環,因此它是 1 條指令,而在您的第二個實現中,您有一個包含 select 的循環(這是一個複雜的函式),而在您的第一個範例中,您有一個包含賦值的循環(即是一個簡單的函式)。這解釋了差異。