为什么oracle存储过程的执行时间会根据其执行方式而大大增加?

2023-11-23

这是我的问题:我们有一个名为的存储过程HEAVY_SP根据执行方式,执行时间会大大增加:

(1)调用执行

在 Oracle SQL Developer IDE 中直接执行

CALL HEAVY_SP(0, 'F', 5, ...)

takes 15秒(我们当前的解决方案)

(2) Using play button

使用 Oracle SQL Developer 打开过程并执行“播放”按钮:

execute procedure

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)


尝试从不同的情况(ide 或 java 程序)获取 nls 参数,它们必须不同

select * from NLS_SESSION_PARAMETERS

然后在存储过程内部设置变量以使它们等于最快的情况。

  execute immediate 'alter session set NLS_SORT=''SPANISH''';

一旦您 SP 拥有所有 nls 参数。它会跑得很快。

我最近刚刚发现一个类似的案例Alter session 通过 Hibernate 减慢查询速度。但在他们的情况下,他们改变了参数,然后变得很慢。

我调查并发现参数 NLS_COMP y NLS_SORT 可能会影响oracle如何使用字符串的执行计划(当它进行比较或排序时)

当 NLS_COMP 定义为 LINGUISTIC 时,它将使用 NLS_SORT 中定义的语言。

例如,如果 NLS_COMP = LINGUISTIC 且 NLS_SORT=BINARY_CI 您的查询 是

select * from table where string_column like 'HI%'

在内部它会做

select * from table where  
NLSSORT(string_column,'BINARI_AI') >= HEXTORAW('324242432')
NLSSORT(string_column,'BINARI_AI') >= HEXTORAW('675757576')

所以如果你没有 NLSSORT(column,'BINARI_AI') 的索引,它会非常慢。

知道 NLS_SORT=BINARY_AI 将使您的排序和比较不区分重音和大小写。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么oracle存储过程的执行时间会根据其执行方式而大大增加? 的相关文章

随机推荐