为什么oracle存储过程的执行时间会大大增加,具体取决于它的执行方式?

这是我的问题:

  • 我们有一个名为: HEAVY_SP的存储过程,在所有场景中都使用相同的参数
  • 我们有一个oracle sql开发人员。 这可以称为: IDE

根据执行方式,执行时间会大大增加:

  • (1)直接在查询窗口(IDE )中 CALL HEAVY_SP(0, 'F', 5, ...) )= 15秒 (我们当前的解决方案)

  • (2)使用IDE = 15秒特殊按钮

  • (3)使用dbms_job(预定执行)= 15秒

作业已安排但未执行。 使用IDE执行作业(右键单击并执行)

  • (4)使用dbms_job(即时执行)= 超过01小时,迭代非常慢

  • (5)从SQL_PLUS(linux)= 超过01小时,迭代很慢

  • (6)从JAVA = 超过01小时,迭代非常慢

  • (7)从TOAD = 超过01小时,迭代非常慢

我们吃了很多谷歌页面如下:

为什么此结果一查询,运行速度较慢,在-A-存储过程超在-的查询窗口

甲骨文-PL-SQL过程的运行-慢于SQL

Oracle的插入输入-存储过程-非常慢-相比对插入件-运行-手动

存储进程内运行-30-慢通过-java的抗磨合直接上的数据库

所以我的问题是:

  • 为什么Oracle以这种方式行事?
  • 它不应该在所有场景(相同的参数)中表现得快吗?
  • 存储过程必须修改?
  • 如果查询计划,跟踪文件或统计信息显示传送行为,则必须修复存储的prodecure?
  • 为什么在查询窗口中执行速度快?

提前致谢。

[编辑]

遵循@BobJarvis关于统计数据的建议

我们的统计数据是最新的。 甚至,我们重新执行了EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SOME_USER', tabname=>'SOME_TABLE', cascade => TRUE); 在所有问题表中,结果是一样的。

[编辑]

遵循@KonstantinSorokin的建议

我怀疑由于会话设置的不同,执行计划可能会有所不同。 考虑比较v$ses_optimizer_env

我们已经调查并且结果是: (1)(4)场景的参数相同。

[编辑]

使用此查询:

 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; 

我注意到机器,程序和ouser的变化取决于测试:

快速模式(查询窗口)

 machine | program | ouser --------------------|------------------ | ------- my laptop username | SQL DEVELOPER | User 

LAG MODE(后台执行)

 machine | program | ouser --------------------|------------------ | ------- ip-10-6-7-1 | oracle@ip-10-6-7-1| rdsdb 

[编辑]

遵循@KonstantinSorokin关于跟踪的建议。

一个临时DBA已经调查过,他告诉我们一些sql_id有不同的执行计划。 他的建议是:使用提示。

这可能是解决方案但是,为什么有些SQL ID有不同的执行计划?

[解决了]

感谢@IsaacMejia, NLS_COMP = LINGUISTIC是缓慢执行的原因。 解决方案必须在实例级别设置NLS_COMP = BINARY ,但为了避免使用此数据库的应用程序中的排序和比较问题,我无法覆盖实例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会话中发现了类似的情况, 通过Hibernate减慢了查询速度 。 但在他们的情况下,他们改变de参数,然后变得缓慢。

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

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

例如,如果NLS_COMP = LINGUISTIC和NLS_SORT = BINARI_AI你的查询是

 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的索引(列,’BINARI_AI’),它将会很慢。

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