英文:
Oracle Join on V$ views becomes extremely slow when a temp table is used
问题
以下是翻译好的代码部分:
我正在尝试从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
如果要查询计划输出,你可以访问以下链接:查询计划输出。
英文:
I am trying to get some information from the Oracle V$ views
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
PLAN_TABLE_OUTPUT
https://pastebin.com/raw/QrkzeHH7
If I remove
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
the query completes in under 17 seconds, while including the inner join with temporary table hc results in the query completing in 5 minutes
Running frequently even causes
ORA-01652: unable to extend temp segment by 128 in tablespace TEMP
I have tried adding /*+ use_hash(bpd hc) */
and /*+ use_hash(ibpd rbsd) */
as hints to force using hash join instead of nested loops but the problem persists.
It's also not clear why the query plan shows left outer joins with recid column when I don't try to join using it.
Can someone throw some light on the query plan?
答案1
得分: 3
以下是代码部分的翻译:
With dictionary queries, you are hitting a bunch of (sometimes complex views) and view merging can really wreak havoc on a plan. My suggestion with these, assuming you have the right joins and there aren't any many-to-many joins here, is to disable view merging (see the two lines of hints below, one in the subquery):
使用字典查询时,您正在访问一堆(有时是复杂的视图),视图合并可能会对计划造成严重破坏。对于这些情况,我的建议是,在假定您有正确的连接并且这里没有多对多连接的情况下,禁用视图合并(请参阅下面子查询中的两行提示):
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
Secondly, it is sometimes necessary to gather fixed object stats (dbms_stats.gather_fixed_objects_stats
).
此外,有时需要收集固定对象统计信息(dbms_stats.gather_fixed_objects_stats
)。
英文:
With dictionary queries, you are hitting a bunch of (sometimes complex views) and view merging can really wreak havoc on a plan. My suggestion with these, assuming you have the right joins and there aren't any many-to-many joins here, is to disable view merging (see the two lines of hints below, one in the subquery):
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
Secondly, it is sometimes necessary to gather fixed object stats (dbms_stats.gather_fixed_objects_stats
).
答案2
得分: 1
I do not have access to your views so cannot test whether this would give the same output but you could try using an analytic COUNT
function so that you do not need to join the tables a second time:
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 )
It's also not clear why the query plan shows left outer joins with
recid
column when I don't try to join using it.
A VIEW
is just a query with a pre-defined SQL statement. When you query from a view then Oracle's SQL engine will rewrite your statement to select from the underlying tables that the view queries and if the statement the view is based on uses a LEFT OUTER JOIN
on a recid
column then the execution plan will show that LEFT OUTER JOIN
on the recid
column between the underlying tables when you query that view. fiddle
英文:
I do not have access to your views so cannot test whether this would give the same output but you could try using an analytic COUNT
function so that you do not need to join the tables a second time:
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 )
> It's also not clear why the query plan shows left outer joins with recid
column when I don't try to join using it.
A VIEW
is just a query with a pre-defined SQL statement. When you query from a view then Oracle's SQL engine will rewrite your statement to select from the underlying tables that the view queries and if the statement the view is based on uses a LEFT OUTER JOIN
on a recid
column then the execution plan will show that LEFT OUTER JOIN
on the recid
column between the underlying tables when you query that view. fiddle
答案3
得分: 0
关于提示和统计数据的说法,我同意,但似乎还有另一个问题,因为出现了错误ORA-01652: 无法通过128扩展临时段在表空间TEMP
。这个错误意味着您选择的数据大小超过了表空间temp的大小,您应该选择少量数据或增加表空间。您可以将查询拆分为两个部分。
英文:
I agree what said about the hint and the statistics but it seems there is another issue becuase of the error ORA-01652: unable to extend temp segment by 128 in tablespace TEMP
. this error means the data you are selecting has bigger size then on tablespace temp, what you should do either select few data or increase the tablespace . you can split the query to two
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论