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

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

相关推荐
a2155833202 小时前
oracle 修改字符集
数据库·oracle
JosieBook12 小时前
【数据库】Oracle迁移至KingbaseES:挑战、策略与最佳实践
数据库·oracle
一只自律的鸡1 天前
【MySQL】第七章 数据库, 表, 数据的增删改查
数据库·oracle
独泪了无痕1 天前
SQL数据类型转换:CAST详解及实践
数据库·sql·oracle
知识分享小能手1 天前
Oracle 19c入门学习教程,从入门到精通,Oracle 用户管理与权限分配 —— 语法详解与实战案例(13)
数据库·学习·oracle
techdashen2 天前
Rust OnceCell 深度解析:延迟初始化的优雅解决方案
开发语言·oracle·rust
90的程序爱好者2 天前
inux定时清理oracle归档日志
oracle
robinson19882 天前
测试崖山是否支持优化器各种消除技术
oracle·崖山·left join消除·标量子查询消除·自定义函数消除·distinct消除·order by消除
知识分享小能手2 天前
Oracle 19c入门学习教程,从入门到精通,Oracle 表分区与索引分区 —— 语法详解与综合实践(12)
数据库·学习·oracle