使用子查询时,Oracle查询运行速度非常慢。这可以纠正吗?

时间:2013-06-19 09:40:47

标签: sql oracle oracle10g

我要为我的项目执行以下查询:

SELECT fcr.request_id,
             DECODE
                (fcpt.user_concurrent_program_name,
                 'Report Set', fcr.description,
                 'Request Set Stage', fcr.description,
                 fcpt.user_concurrent_program_name
                ) user_concurrent_program_name,
             fcr.description, fcr.argument_text, fcr.concurrent_program_id,
             fcr.parent_request_id, fcr.actual_start_date,
             fcr.actual_completion_date,
             ROUND (  (fcr.actual_completion_date - fcr.actual_start_date)
                    * 24
                    * 60,
                    4
                   ) runtime,
             DECODE (fcr.phase_code, 'C', 'No Schedule') program_status,
             fu.user_name, frt.responsibility_name, fcr.logfile_name
        FROM apps.fnd_concurrent_requests@db_link fcr,
             apps.fnd_concurrent_programs_tl@db_link fcpt,
             apps.fnd_user@db_link fu,
             apps.fnd_responsibility_tl@db_link frt
       WHERE fcr.concurrent_program_id = fcpt.concurrent_program_id
         AND fcr.requested_by = fu.user_id
         AND fcr.responsibility_id = frt.responsibility_id
         AND fcr.responsibility_application_id = frt.application_id
         AND fcr.actual_completion_date >= (SELECT MAX (alert_logged_time)
                                          FROM allen.main_table
                                         WHERE program_status = 'No Schedule')
         AND fcr.phase_code = 'C';

但是上面的查询运行时间太长。当我给出相应的时间作为输入时,而不是

SELECT MAX (alert_logged_time) 
FROM allen.main_table 
WHERE program_status = 'No Schedule'

我很快就得到了输出。为什么会这样?无论如何要纠正这个?

3 个答案:

答案 0 :(得分:2)

我怀疑这种差异的原因是原始的慢查询包含远程本地表,而修改后的查询只有远程表< /强>

当Oracle查询本地和远程表的混合时,它必须决定连接的发生位置。如果要在本地执行连接,因为默认情况下通常首选连接,则远程表中的所有数据都将通过数据库链接传输。传输的数据量可能比查询的实际结果大许多倍。

另一方面,当所有表在查询中都是远程的时,只传输查询结果,而计算则在远程站点进行。

您可以使用/*+ DRIVING_SITE (<table_alias>)*/提示指示Oracle在指定表的站点执行连接,从而限制来回传输的数据量。

在查询中添加提示/*+ DRIVING_SITE(fcr) */应该使其作为修改后的查询执行。

答案 1 :(得分:1)

由于您的子查询符合Oracle scalar subquery caching功能的条件,因此我怀疑性能下降的原因可能是任何(或两者)的缺失索引:

  • allen.main_table.program_status
  • allen.main_table.alert_logged_time

答案 2 :(得分:1)

你可以尝试使用连接

SELECT fcr.request_id,
             DECODE
                (fcpt.user_concurrent_program_name,
                 'Report Set', fcr.description,
                 'Request Set Stage', fcr.description,
                 fcpt.user_concurrent_program_name
                ) user_concurrent_program_name,
             fcr.description, fcr.argument_text, fcr.concurrent_program_id,
             fcr.parent_request_id, fcr.actual_start_date,
             fcr.actual_completion_date,
             ROUND (  (fcr.actual_completion_date - fcr.actual_start_date)
                    * 24
                    * 60,
                    4
                   ) runtime,
             DECODE (fcr.phase_code, 'C', 'No Schedule') program_status,
             fu.user_name, frt.responsibility_name, fcr.logfile_name
        FROM apps.fnd_concurrent_requests@aadsp_to_acptr fcr,
             apps.fnd_concurrent_programs_tl@aadsp_to_acptr fcpt,
             apps.fnd_user@aadsp_to_acptr fu,
             apps.fnd_responsibility_tl@aadsp_to_acptr frt,
             (SELECT MAX (alert_logged_time) as max_time
              FROM allen.main_table
              WHERE program_status = 'No Schedule')  SQ
       WHERE fcr.concurrent_program_id = fcpt.concurrent_program_id
         AND fcr.requested_by = fu.user_id
         AND fcr.responsibility_id = frt.responsibility_id
         AND fcr.responsibility_application_id = frt.application_id
         AND fcr.actual_completion_date >= SQ.max_time
         AND fcr.phase_code = 'C';