测试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秒

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

相关推荐
量子物理学1 小时前
oracle plsql instantclient 安装
数据库·oracle
悟道书生20 小时前
(一)Navicate为什么转存结构和数据只转存表而不包含建库?
数据库·oracle
时间售卖铺1 天前
Oracle DQL精髓:从基础到高级实战
运维·数据库·云原生·oracle
lusklusklusk1 天前
SQL Server 为什么普通 SELECT 会阻塞 UPDATE?——行级 S 锁到表级 S 锁的锁升级原理与实验验证
数据库·mysql·oracle
瑶总迷弟1 天前
银河麒麟 V10 ARM64 安装 Oracle 19c 静默部署操作手册
数据库·oracle
RuoyiOffice1 天前
SpringBoot3 + openGauss:RuoYi Office 登录、流程发布与用印填报适配实战
java·数据库·spring boot·opengauss·信创
lusklusklusk2 天前
Python 巡检脚本:进程运行状态、数据库写入时效检查及邮件通知与告警
数据库·python·oracle
悟道书生2 天前
Kingbase数据库使用命令来执行init.sql(包含建库建表语句)
数据库·oracle
晴天¥2 天前
记一次Oracle 归档进程卡死怎么去有效排查
数据库·oracle
梦幻通灵2 天前
MybatisPlus使用数据库递增ID实现方案【持续更新】
数据库·oracle