JRi*_*dsz 7 java oracle toad stored-procedures oracle-sqldeveloper
这是我的问题:我们有一个称为的存储过程,HEAVY_SP并且根据其执行方式,执行时间会大大增加:
(1)通话执行
在Oracle SQL Developer IDE中直接执行
CALL HEAVY_SP(0, 'F', 5, ...)
Run Code Online (Sandbox Code Playgroud)
需要15秒(我们当前的解决方案)
(2)使用播放按钮
使用Oracle SQL Developer打开过程并执行“播放”按钮:
需要15秒
(3) dbms_job:计划模式
需要15秒
(4) dbms_job:即时执行模式
需要超过1个小时
回顾数据处理方式,我们发现每次迭代都很慢。
(5)从SQL_PLUS(Linux)
耗时超过1小时,迭代速度非常慢
(6)从JAVA
耗时超过1小时,迭代速度非常慢
(7)从TOAD
耗时超过1小时,迭代速度非常慢
研究
我们已经吃了很多Google页面,例如:
oracle-pl-sql-procedure-runs比SQL慢
通过Java相对于直接在数据库上运行,存储过程运行30慢一些
提前致谢。
提示1
遵循@BobJarvis关于统计的建议
结果:我们的统计数据是最新的。甚至,我们EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SOME_USER', tabname=>'SOME_TABLE', cascade => TRUE);在所有问题表中重新执行,结果是相同的。
提示#2
遵循@KonstantinSorokin的建议
我怀疑执行计划可能会因会话设置的不同而有所不同。考虑比较v$ses_optimizer_env
结果:我们进行了比较,结果(1)和(4)的v $ ses_optimizer_env相同。
提示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;
Run Code Online (Sandbox Code Playgroud)
我注意到机器,程序和其他更改取决于测试:
快速模式(查询窗口)
machine | program | ouser
--------------------|------------------ | -------
my laptop username | SQL DEVELOPER | User
Run Code Online (Sandbox Code Playgroud)
滞后模式(后台执行)
machine | program | ouser
--------------------|------------------ | -------
ip-10-6-7-1 | oracle@ip-10-6-7-1| rdsdb
Run Code Online (Sandbox Code Playgroud)
提示#4
遵循@KonstantinSorokin与痕迹相关的建议。
结果:临时DBA进行了调查,他告诉我们某些sql_id具有不同的执行计划。他的建议是:使用提示。
这可能是解决方案,但是,为什么某些SQL ID具有不同的执行计划?
感谢@ IsaacMejia,NLS_COMP = LINGUISTIC是缓慢执行的原因。因此,java不是问题的原因。Oracle错误配置是导致我们出现问题的原因。
解决方案必须在实例级别为NLS_COMP = BINARY设置正确的值。
但就我而言,我有几个应用程序可以很好地处理此值。因此,为了避免应用程序中的排序和比较问题,我无法覆盖实例NLS设置。
临时解决方案在存储过程的开头执行:
execute immediate 'alter session set NLS_COMP=''BINARY''';
Run Code Online (Sandbox Code Playgroud)
并在完成时返回到先前的值:
execute immediate 'alter session set NLS_COMP=''LINGUISTIC''';
Run Code Online (Sandbox Code Playgroud)
现在,存储过程可以像在查询窗口中直接执行一样快速运行(ORACLE SQL DEVELOPER)
小智 5
尝试从您的不同情况(ide 或 java 程序)中获取 nls 参数,它们必须不同
select * from NLS_SESSION_PARAMETERS
Run Code Online (Sandbox Code Playgroud)
然后在您的存储过程中设置变量,使它们在最快的情况下相等。
execute immediate 'alter session set NLS_SORT=''SPANISH''';
Run Code Online (Sandbox Code Playgroud)
一旦 SP 拥有所有 nls 参数。它会跑得很快。
我最近在Alter session 中发现了一个类似的案例,通过 Hibernate 减慢了查询速度。但在他们的情况下,他们改变了参数,然后变得很慢。
我调查发现参数 NLS_COMP y NLS_SORT 可能会影响oracle如何使用字符串执行计划(比较或排序时)
当 NLS_COMP 定义为 LINGUISTIC 时,它将使用 NLS_SORT 中定义的语言。
例如,如果 NLS_COMP = LINGUISTIC 和 NLS_SORT=BINARI_AI 您的查询是
select * from table where string_column like 'HI%'
Run Code Online (Sandbox Code Playgroud)
在内部它会做
select * from table where
NLSSORT(string_column,'BINARI_AI') >= HEXTORAW('324242432')
NLSSORT(string_column,'BINARI_AI') >= HEXTORAW('675757576')
Run Code Online (Sandbox Code Playgroud)
所以如果你没有 NLSSORT(column,'BINARI_AI') 的索引,它会很慢。
知道 NLS_SORT=BINARY_AI 将使您的排序和比较不区分重音和不区分大小写。