Spørgsmål 1:Det ser ud til, at der ikke er noget om beregningstid, bare fejl i optimeringsalgoritmen, som gør det galt, mens man beregner en plan for den bedste udførelse.
Spørgsmål 2:Der er en række kendte og rettede fejl i Oracle 11.X.0.X relateret til optimering af indlejrede forespørgsler og query factoring. Men det er meget svært at finde et konkret problem.
Spørgsmål 3:Der er to udokumenterede tip:materialize
og inline
men ingen af dem virker for mig, mens jeg prøvede dit eksempel. Det er muligt, at nogle ændringer i serverkonfigurationen eller opgradering til 11.2.0.3 kan øge grænsen for indlejret with
klausuler:for mig (på 11.2.0.3 Win7/x86) fungerer dit eksempel fint, men et stigende antal indlejrede tabeller til 30 hænger en session.
Løsningen kan se sådan ud:
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
)
Det virker i det mindste for mig på nesting-niveau på 30 og producerer en helt anden eksekveringsplan med WINDOW BUFFER
og VIEW
i stedet for LOAD TABLE AS SELECT
, SORT AGGREGATE
og TABLE ACCESS FULL
.
Opdater
-
Har lige installeret 11.2.0.4 (Win7/32bit) og test det mod den første forespørgsel. Intet ændret i optimeringsadfærd.
-
Der er ingen mulighed for direkte at påvirke en CBO-adfærd, selv med brug af
inline
(udokumenteret) ellerRULE
(forældede) hints. Måske en guru kender en variant, men det er en tophemmelighed for mig (og Google også :-) . -
At gøre ting i en one select-sætning inden for rimelig tid er muligt, hvis en hovedselektionssætning er adskilt i dele og placeret i funktionen, som returnerer et sæt rækker (funktion, der returnerer sys_refcursor eller stærk indtastet cursor), men det er ikke et valg, hvis en forespørgsel konstrueret under kørsel.
-
Løsning med brug af XML er mulig,
men denne variant ligner at fjerne en tonsil gennem røvhullet(undskyld):
.
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
)
)
)
)))
En anden ting ved en mærkelig kode ovenfor er, at denne variant kun gælder, hvis with
datasæt havde ikke et stort antal rækker.