Q1:Scheint, dass es nichts über die Berechnungszeit gibt, nur Fehler im Optimierungsalgorithmus, die ihn bei der Berechnung eines Best-Execution-Plans verrückt machen.
F2:Es gibt eine Reihe bekannter und behobener Fehler in Oracle 11.X.0.X im Zusammenhang mit der Optimierung von verschachtelten Abfragen und der Faktorisierung von Abfragen. Aber es ist sehr schwer, ein konkretes Problem zu finden.
F3:Es gibt zwei undokumentierte Hinweise:materialize
und inline
aber keiner von ihnen funktioniert für mich, während ich Ihr Beispiel ausprobiert habe. Es ist möglich, dass einige Änderungen in der Serverkonfiguration oder ein Upgrade auf 11.2.0.3 das Limit für verschachtelte with
erhöhen Klauseln:Für mich (auf 11.2.0.3 Win7/x86) funktioniert Ihr Beispiel gut, aber die Erhöhung der Anzahl verschachtelter Tabellen auf 30 hängt eine Sitzung auf.
Abhilfe könnte wie folgt aussehen:
select k from (
select k, avg(k) over (partition by null) k_avg from ( --t16
select k, avg(k) over (partition by null) k_avg from ( --t15
select k, avg(k) over (partition by null) k_avg from ( --t14
select k, avg(k) over (partition by null) k_avg from ( --t13
select k, avg(k) over (partition by null) k_avg from ( --t12
select k, avg(k) over (partition by null) k_avg from ( --t11
select k, avg(k) over (partition by null) k_avg from ( --t10
select k, avg(k) over (partition by null) k_avg from ( --t9
select k, avg(k) over (partition by null) k_avg from ( --t8
select k, avg(k) over (partition by null) k_avg from ( --t7
select k, avg(k) over (partition by null) k_avg from ( --t6
select k, avg(k) over (partition by null) k_avg from ( --t5
select k, avg(k) over (partition by null) k_avg from ( --t4
select k, avg(k) over (partition by null) k_avg from ( --t3
select k, avg(k) over (partition by null) k_avg from ( --t2
select k, avg(k) over (partition by null) k_avg from ( -- t1
select k, avg(k) over (partition by null) k_avg from (select 0 as k from dual) t0
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
) where k >= k_avg
)
Zumindest funktioniert es für mich auf Verschachtelungsebene von 30 und erzeugt einen völlig anderen Ausführungsplan mit WINDOW BUFFER
und VIEW
statt LOAD TABLE AS SELECT
, SORT AGGREGATE
und TABLE ACCESS FULL
.
Aktualisieren
-
Einfach 11.2.0.4 (Win7/32bit) installiert und mit der ersten Abfrage getestet. Am Optimiererverhalten hat sich nichts geändert.
-
Es gibt keine Möglichkeit, ein CBO-Verhalten direkt zu beeinflussen, auch nicht bei Verwendung von
ist es streng geheiminline
(undokumentiert) oderRULE
(veraltete) Hinweise. Vielleicht kennt irgendein Guru eine Variante, aber für mich (und Google auch :-) . -
Es ist möglich, Dinge in einer One-Select-Anweisung in angemessener Zeit zu erledigen, wenn eine Haupt-Select-Anweisung in Teile getrennt und in die Funktion eingefügt wird, die eine Reihe von Zeilen zurückgibt (Funktion, die sys_refcursor oder einen stark typisierten Cursor zurückgibt), aber es ist keine Wahl, wenn eine Abfrage zur Laufzeit erstellt.
-
Problemumgehung mit Verwendung von XML ist möglich,
aber diese Variante sieht aus wie das Entfernen einer Mandel durch das Arschloch(Entschuldigung):
.
select
extractvalue(column_value,'/t/somevalue') abc
from
table(xmlsequence((
select t2 from (
select
t0,
t1,
(
select xmlagg(
xmlelement("t",
xmlelement("k1",extractvalue(t1t.column_value,'/t/k1')),
xmlelement("somevalue", systimestamp))
)
from
table(xmlsequence(t0)) t0t,
table(xmlsequence(t1)) t1t
where
extractvalue(t1t.column_value,'/t/k1') >= (
select avg(extractvalue(t1t.column_value, '/t/k1')) from table(xmlsequence(t1))
)
and
extractvalue(t0t.column_value,'/t/k2') > 6
) t2
from (
select
t0,
(
select xmlagg(
xmlelement("t",
xmlelement("k1",extractvalue(column_value,'/t/k1')),
xmlelement("somevalue", sysdate))
)
from table(xmlsequence(t0))
where
extractvalue(column_value,'/t/k1') >= (
select avg(extractvalue(column_value, '/t/k1')) from table(xmlsequence(t0))
)
) t1
from (
select
xmlagg(xmlelement("t", xmlelement("k1", level), xmlelement("k2", level + 3))) t0
from dual connect by level < 5
)
)
)
)))
Eine andere Sache über einen seltsamen Code oben ist, dass diese Variante nur anwendbar ist, wenn with
Datensätze hatten keine große Anzahl von Zeilen.