您应该使用更好的资源来理解PLSQL_OPTIMIZE_LEVEL,并且您应该确保以正确的方式测试正确的东西。
1。 PLSQL_OPTIMIZE_LEVEL 是如何工作的?
了解任何参数的最佳方式是使用官方文档中的数据库参考。参数PLSQL_OPTIMIZE_LEVEL 经常更改,因此请确保参考准确的版本。网上有很多非官方的、过时的信息,但here's the relevant text for 18c:
0
维护评估顺序和副作用模式,
Oracle9i 和更早版本的异常和程序包初始化
发布。还删除了 BINARY_INTEGER 的新语义标识和
PLS_INTEGER 并恢复早期的评估规则
整数表达式。虽然代码会比它运行得快一些
在 Oracle9i 中,使用 0 级将丧失大部分性能
Oracle Database 10g 中 PL/SQL 的优势。
1
对 PL/SQL 程序进行广泛的优化,包括
消除不必要的计算和异常,但通常
不会将源代码移出其原始源顺序。
2
应用广泛的现代优化技术
级别 1 包括可能将源代码移动相对较远的更改
从原来的位置。
3
应用范围广泛的优化技术超出了水平
2,自动包含未特别要求的技术。
这种描述很难判断何时会发生内联。听起来内联可能发生在级别 1,可能发生在级别 2。我下面的测试显示从 0 到 1 的内联性能差异很大,与1比2,和2比3没有区别。
但是很多行为都没有记录,所以很难判断什么时候会发生哪种优化。
2。设置关卡后是否重新编译代码?
仅仅设置会话值是不够的,还必须重新编译程序,如下:
alter session set plsql_optimize_level=3;
alter procedure call_proc_arith compile;
alter procedure p1 compile;
3。你真的在测试内联吗?
您的过程包含大量循环和过程调用,但我认为您的数字倒数了。要测试内联,您必须让大循环调用该过程,而小循环进行计数。只有 10 个过程调用,您永远不会注意到编译器的差异。
我使用这些程序进行测试:
create or replace procedure p2 is
n number:=0;
begin
for i in 1..5 loop
n:=n+1;
end loop;
end;
/
create or replace procedure CALL_PROC_ARITH2 is
begin
for i in 1..10000000 loop
p2;
end loop;
end;
/
--Check the PL/SQL optimize level for the objects.
select name, plsql_optimize_level, plsql_code_type
from all_plsql_object_settings
where owner = user
and name like 'CALL_PROC%' or name like 'P_';
4。您的测试方法是否足够稳健?
您的测试应该尝试补偿其他消耗 CPU 的活动。以交替顺序运行多个小测试,抛出高值和低值,并比较平均值。与两次运行 5 分钟的测试相比,5 秒的差异并不显着。
我使用以下 PL/SQL 块来测试运行时间。 (您可以构建一个 PL/SQL 程序以随机顺序运行块并记录时间。我手动完成了该部分。)级别 3 和 2 运行速度相同,级别 1 慢一点,级别 0 显着慢一点。
--Level 3: 3.331, 3.403, 3.419
alter session set plsql_optimize_level = 3;
alter procedure call_proc_arith2 compile;
alter procedure p2 compile;
begin
call_proc_arith2;
end;
/
--Level 2: 3.383, 3.470, 3.444
alter session set plsql_optimize_level = 2;
alter procedure call_proc_arith2 compile;
alter procedure p2 compile;
begin
call_proc_arith2;
end;
/
--Level 1: 3.867, 3.859, 3.873
alter session set plsql_optimize_level = 1;
alter procedure call_proc_arith2 compile;
alter procedure p2 compile;
begin
call_proc_arith2;
end;
/
--Level 0: 6.286, 6.296, 6.315
alter session set plsql_optimize_level = 0;
alter procedure call_proc_arith2 compile;
alter procedure p2 compile;
begin
call_proc_arith2;
end;
/
5。你甚至关心 PL/SQL 优化吗?
在大多数实际的 PL/SQL 程序中,内联过程不会产生有意义的差异。最佳实践是尽可能多地使用 SQL 进行繁重的工作。但无论您的逻辑在哪里,请确保您使用的是分析器,并且只调整需要大量时间的程序部分。在调整 PL/SQL 程序的一部分之前,您应该有一些硬数字,例如“如果我优化第 X 行,程序的运行速度可以提高 Y%。”