测试Oracle-PG-DM-崖山-openGauss游标LOOP性能

PLSQL开发应该尽量避免使用游标,乱用游标会引起严重性能问题

最近几年做过很多ORACLE EBS优化项目,除了乱写SQL导致性能问题之外,影响性能最大的就是乱用游标

如果是INSERT,直接INSERT INTO SELECT,或者INSERT /*+ PARALLEL(6) ENABLE_PARALLEL_DML */ SELECT...,不要用游标LOOP循环单行INSERT

如果是UPDATE,DELETE,为了避免大事务,可以用ROWID+批量游标,根据数据集大小1-10W行提交一次

如果是要做复杂的计算,可以用临时表存放SQL多表关联的中间结果集,不要游标套游标来做复杂计算

数据量少(10w行内),如果没有游标套游标,如果游标中没有复杂慢SQL,如果游标中没有胡乱调用复杂自定义函数,可以适当使用游标

数据量很少,爱咋咋用

虽然我们嘴上说要尽量避免使用游标,但是有时候很多PLSQL代码都已经写了10-20年了,里面大量使用了游标,木已成舟,不可能推翻重来了

现在来测试Oracle-PG-DM-崖山-openGauss游标LOOP性能,看看国产库游标LOOP性能和Oracle差距有多大

如果国产库游标LOOP性能和Oracle差距不大,就加测游标LOOP+INSERT,批量游标,如果性能差距太大就不测了,免得丢人

TEST01数据来自DBA_OBJECTS,重复512次,共4500W行,不创建索引

测试PLSQL代码如下

复制代码
begin
  for cur in (select object_id from test01) loop
   null;  ---无计算,测试纯LOOP性能
  end loop;
end;
/

declare
  v_cnt number := 0;
begin
  for cur in (select object_id from test01) loop
    v_cnt:=v_cnt+cur.object_id; ---带计算,测试LOOP循环计算性能
  end loop;
  dbms_output.put_line(v_cnt);
end;
/

开始测试(多次运行,确保TEST01被CACHE在内存中)

Oracle11.2.0.4

复制代码
SQL> begin
  for cur in (select object_id from test01) loop
   null;
  end loop;
end;
/  2    3    4    5    6  

PL/SQL procedure successfully completed.

Elapsed: 00:00:07.56

SQL> declare
  v_cnt number := 0;
begin
  for cur in (select object_id from test01) loop
    v_cnt:=v_cnt+cur.object_id;
  end loop;
  dbms_output.put_line(v_cnt);
end;
/  2    3    4    5    6    7    8    9  
1953663546368

PL/SQL procedure successfully completed.

Elapsed: 00:00:08.85

PG18

复制代码
postgres=# do $$
postgres$# declare
postgres$#   cur record;
postgres$# begin
postgres$#   for cur in select object_id from test01
postgres$#   loop
postgres$#     null;
postgres$#   end loop;
postgres$# end $$;
DO
Time: 9259.170 ms (00:09.259)

postgres=# do $$
postgres$# declare
postgres$#   v_cnt numeric := 0;
postgres$#   cur record;
postgres$# begin
postgres$#   for cur in select object_id from test01
postgres$#   loop
postgres$#     v_cnt := v_cnt + cur.object_id;
postgres$#   end loop;
postgres$#   raise notice 'Result: %', v_cnt;
postgres$# end $$;
NOTICE:  Result: 1953663546368
DO
Time: 15820.366 ms (00:15.820)

DM8

复制代码
SQL> begin
  for cur in (select object_id from test01) loop
   null;  
  end loop;
end;
/
2   3   4   5   6   
DMSQL executed successfully
used time: 00:00:17.230. Execute id is 604.

SQL> declare
  v_cnt number := 0;
begin
  for cur in (select object_id from test01) loop
    v_cnt:=v_cnt+cur.object_id; 
  end loop;
  dbms_output.put_line(v_cnt);
end;
/2   3   4   5   6   7   8   9   
DMSQL executed successfully
used time: 00:00:21.558. Execute id is 605.

崖山23.5.1

复制代码
SQL> begin
  for cur in (select object_id from test01) loop
   null;  
  end loop;
end;
/   2    3    4    5    6 

PL/SQL Succeed.

Elapsed: 00:00:17.487

SQL> declare
  v_cnt number := 0;
begin
  for cur in (select object_id from test01) loop
    v_cnt:=v_cnt+cur.object_id; 
  end loop;
  dbms_output.put_line(v_cnt);
end;
/   2    3    4    5    6    7    8    9 

PL/SQL Succeed.

Elapsed: 00:00:24.163

openGauss7.0

复制代码
openGauss=# begin
openGauss$#   for cur in (select object_id from test01) loop
openGauss$#    null;
openGauss$#   end loop;
openGauss$# end;
openGauss$# /
ANONYMOUS BLOCK EXECUTE
Time: 10391.383 ms

openGauss=# declare
openGauss-#   v_cnt number := 0;
openGauss-# begin
openGauss$#   for cur in (select object_id from test01) loop
openGauss$#     v_cnt:=v_cnt+cur.object_id;
openGauss$#   end loop;
openGauss$#   RAISE NOTICE 'Result: %', v_cnt;
openGauss$# end;
openGauss$# /
NOTICE:  Result: 1953663546368
ANONYMOUS BLOCK EXECUTE
Time: 26544.038 ms

测试结果汇总如下图所示:

结论:

Oracle游标LOOP循环性能最好,游标LOOP带计算性能损失1.29秒

PG游标LOOP循环性能很好,游标LOOP带计算性性能损失6.56秒

DM游标LOOP循环性能不好,游标LOOP带计算性能损失4.32秒

崖山游标LOOP循环性能不好,游标LOOP带计算性能损失6.67秒

openGauss游标LOOP性能很好,游标LOOP带计算性能差16.15秒

国产库在游标处理的性能上还有很大性能提升空间

相关推荐
jnrjian2 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle
TTc_2 天前
oracle中的union和union all有什么区别?
数据库·oracle
山峰哥2 天前
吃透 SQL 优化:告别慢查询,解锁数据库高性能
服务器·数据库·sql·oracle·性能优化·编辑器
南 阳2 天前
Python从入门到精通day37
数据库·python·oracle
轩情吖3 天前
MySQL库的操作
android·数据库·mysql·oracle·字符集·数据库操作·编码集
脱发的老袁3 天前
【数据库】Oracle手动清理归档日志
数据库·oracle
jnrjian3 天前
Oracle 共享池 库缓存下的 Library Cache Lock
数据库·缓存·oracle
新缸中之脑3 天前
在Reddit上探索未满足的需求
数据库·oracle
light blue bird3 天前
产线多并发客户端指令操作场景组件
jvm·oracle·.net·winform
坐吃山猪4 天前
Neo4j04_数据库事务
数据库·oracle·neo4j