使用临时表时,V$视图上的Oracle连接会变得非常慢

2o7dmzc5  于 2023-03-17  发布在  Oracle
关注(0)|答案(3)|浏览(223)

我正在尝试从Oracle V$视图中获取一些信息

SELECT bpd.handle,bpd.media,bpd.copy#, bpd.bytes, bpd.session_key, bsjd.operation,bsjd.start_time, bsjd.end_time,bpd.completion_time,  
bsd.controlfile_included
FROM v$backup_piece_details bpd 
INNER JOIN v$rman_backup_subjob_details bsjd ON bpd.SESSION_KEY = bsjd.session_key
INNER JOIN v$backup_set_details bsd ON bpd.set_stamp = bsd.set_stamp AND bpd.set_count = bsd.set_count
INNER JOIN 
(SELECT ibpd.session_key, count (ibpd.handle) count FROM v$backup_piece_details ibpd 
INNER JOIN v$rman_backup_subjob_details rbsd ON IBPD.session_key = rbsd.SESSION_KEY
GROUP BY IBPD.session_key, IBPD.handle) hc
ON hc.session_key = bpd.SESSION_KEY

计划表输出
https://pastebin.com/raw/QrkzeHH7
如果我把

INNER JOIN 
(SELECT ibpd.session_key, count (ibpd.handle) count FROM v$backup_piece_details ibpd 
INNER JOIN v$rman_backup_subjob_details rbsd ON IBPD.session_key = rbsd.SESSION_KEY
GROUP BY IBPD.session_key, IBPD.handle) hc
ON hc.session_key = bpd.SESSION_KEY

查询在17秒内完成,而包含与临时表hc的内连接会导致查询在5分钟内完成频繁运行甚至会导致

ORA-01652: unable to extend temp segment by 128 in tablespace TEMP

我尝试添加/*+ use_hash(bpd hc) *//*+ use_hash(ibpd rbsd) */作为提示,强制使用散列连接而不是嵌套循环,但问题仍然存在。
也不清楚为什么查询计划显示与recid列的左外连接,而我没有尝试使用它进行连接。
有人能解释一下查询计划吗?

y1aodyip

y1aodyip1#

使用字典查询时,你会遇到一堆视图(有时候是复杂的视图),视图合并可能会对计划造成严重破坏。我的建议是,假设你有正确的连接,并且这里没有任何多对多连接,那么就禁用视图合并(参见下面的两行提示,其中一行在子查询中):

SELECT /*+ NO_MERGE(bpd) NO_MERGE(bsjd) NO_MERGE(bsd) */
      bpd.handle,
       bpd.media,
       bpd.copy#,
       bpd.bytes,
       bpd.session_key,
       bsjd.operation,
       bsjd.start_time,
       bsjd.end_time,
       bpd.completion_time,
       bsd.controlfile_included
  FROM v$backup_piece_details bpd
   INNER JOIN v$rman_backup_subjob_details bsjd
                  ON bpd.SESSION_KEY = bsjd.session_key
   INNER JOIN v$backup_set_details bsd
                  ON bpd.set_stamp = bsd.set_stamp
                     AND bpd.set_count = bsd.set_count
   INNER JOIN (SELECT /*+ NO_MERGE NO_MERGE(ibpd rbsd) */
                     ibpd.session_key,
                     COUNT (ibpd.handle) COUNT
                FROM v$backup_piece_details ibpd
                 INNER JOIN v$rman_backup_subjob_details rbsd
                                ON IBPD.session_key = rbsd.SESSION_KEY
            GROUP BY IBPD.session_key,
                     IBPD.handle) hc
                  ON hc.session_key = bpd.SESSION_KEY

其次,有时需要收集固定对象统计信息(dbms_stats.gather_fixed_objects_stats)。

a9wyjsp7

a9wyjsp72#

我无法访问您的视图,因此无法测试这是否会给予相同的输出,但您可以尝试使用一个分析COUNT函数,这样就不需要第二次连接表:

SELECT s.*,
       bsd.controlfile_included
FROM   ( SELECT bpd.handle,
                bpd.media,
                bpd.copy#,
                bpd.bytes,
                bpd.session_key,
                bsjd.operation,
                bsjd.start_time,
                bsjd.end_time,
                bpd.completion_time,
                COUNT(bpd.handle) OVER (PARTITION BY bpd.session_key, bpd.handle)
                  AS handle_count,
                bpd.set_stamp
         FROM   v$backup_piece_details bpd 
                INNER JOIN v$rman_backup_subjob_details bsjd
                ON bpd.SESSION_KEY = bsjd.session_key
       ) s
       INNER JOIN v$backup_set_details bsd
       ON ( s.set_stamp = bsd.set_stamp AND s.set_count = bsd.set_count )

也不清楚为什么查询计划显示与recid列的左外连接,而我没有尝试使用它进行连接。
VIEW只是一个具有预定义SQL语句的查询。当您从视图查询时,Oracle'的SQL引擎将重写您的语句,以便从视图查询的基础表中进行选择,如果视图所基于的语句在recid列上使用LEFT OUTER JOIN,则执行计划将显示recid列上的LEFT OUTER JOIN位于基础当您查询该视图时。fiddle

f87krz0w

f87krz0w3#

我同意关于提示和统计信息的说法,但似乎还有另一个问题,因为错误ORA-01652: unable to extend temp segment by 128 in tablespace TEMP。此错误意味着您选择的数据比临时表空间上的数据大,您应该选择较少的数据或增加表空间。您可以将查询拆分为两个

相关问题