这是我的问题:我们有一个名为的存储过程HEAVY_SP
根据执行方式,执行时间会大大增加:
(1)调用执行
在 Oracle SQL Developer IDE 中直接执行
CALL HEAVY_SP(0, 'F', 5, ...)
takes 15秒(我们当前的解决方案)
(2) Using play button
使用 Oracle SQL Developer 打开过程并执行“播放”按钮:
takes 15秒
(3)dbms_job :计划模式
takes 15秒
(4)dbms_job :即时执行模式
takes 1个多小时
回顾数据的处理方式,我们发现每次迭代都非常慢。
(5)来自 SQL_PLUS (linux)
Takes 1个多小时,迭代非常慢
(6)来自JAVA
Takes 1个多小时,迭代非常慢
(7)来自蟾蜍
Takes 1个多小时,迭代非常慢
Research
我们吃过很多google页面,比如下面的:
为什么查询在存储过程中运行速度比在查询窗口中慢
oracle-pl-sql-procedure-runs-slower-than-sql
与手动运行插入相比,oracle 在存储过程中插入非常慢
存储过程运行 30 通过 Java 与直接在数据库上运行速度较慢
所以我的问题是:
- 为什么 Oracle 会这样做?
- 它不应该在所有场景(相同参数)下都表现得很快吗?
- 存储过程必须修改吗?
- 如果查询计划、跟踪文件或统计信息显示不同的行为,则必须修复存储过程?
- 为什么查询窗口执行速度快?
提前致谢。
评论中的提示
TIP #1
遵循以下建议@鲍勃·贾维斯关于统计
Result:我们的统计数据是最新的。甚至,我们被处决了EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SOME_USER', tabname=>'SOME_TABLE', cascade => TRUE);
在所有有问题的表中,结果是相同的。
TIP #2
遵循以下建议@康斯坦丁索罗金
我怀疑由于会话设置的不同,执行计划可能会有所不同。考虑比较v$ses_optimizer_env
Result: 我们比较了结果v$ses_optimizer_env是一样的(1) and (4)场景。
TIP #3
使用此查询:
select s.sid,s.serial#,s.username, s.machine,replace(q.SQL_FULLTEXT,chr(0)) sql_text, s.program, s.logon_time, s.status, s.OSUSER
from v$session s, v$sql q
where
s.status='ACTIVE'
and s.username is not null
and s.sql_hash_value = q.hash_value
order by s.LOGON_TIME, s.username;
我注意到机器、程序和用户会根据测试而变化:
快速模式(查询窗口)
machine | program | ouser
--------------------|------------------ | -------
my laptop username | SQL DEVELOPER | User
LAG 模式(后台执行)
machine | program | ouser
--------------------|------------------ | -------
ip-10-6-7-1 | oracle@ip-10-6-7-1| rdsdb
TIP #4
遵循以下建议@康斯坦丁索罗金与痕迹有关。
Result:一位临时 DBA 进行了调查,他告诉我们某些 sql_id 有不同的执行计划。他的建议是:使用提示。
这可能是解决方案,但是,为什么某些 SQL ID 有不同的执行计划?
[SOLVED]
感谢@IsaacMejia,NLS_COMP=语言是执行缓慢的原因。所以java不是问题的原因。 Oracle 错误配置是导致我们问题的原因。
解决方案必须设置正确的值NLS_COMP=二进制在实例级别。
但就我而言,我有几个应用程序可以很好地使用此值。因此,为了避免应用程序中出现排序和比较问题,我无法覆盖实例 NLS 设置。
临时解决方案是在存储过程的开头执行:
execute immediate 'alter session set NLS_COMP=''BINARY''';
并在完成时返回到先前的值:
execute immediate 'alter session set NLS_COMP=''LINGUISTIC''';
现在存储过程运行得像直接在查询窗口中执行一样快(ORACLE SQL DEVELOPER)