Q1:Parece que não há nada sobre o tempo de cálculo, apenas bug no algoritmo do otimizador que o torna louco ao calcular o melhor plano de execução.
Q2:Existem vários bugs conhecidos e corrigidos no Oracle 11.X.0.X relacionados à otimização de consultas aninhadas e fatoração de consultas. Mas é muito difícil encontrar um problema concreto.
Q3:Há dois não documentados dicas:
materialize
e inline
mas nenhum deles funciona para mim enquanto eu tentei o seu exemplo. É possível que algumas mudanças na configuração do servidor ou atualização para 11.2.0.3 possam aumentar o limite de with
aninhado cláusulas:para mim (em 11.2.0.3 Win7/x86) seu exemplo funciona bem, mas aumentar o número de tabelas aninhadas para 30 trava uma sessão. A solução alternativa pode ter esta aparência:
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
)
Pelo menos funciona para mim no nível de aninhamento de 30 e produz um plano de execução totalmente diferente com
WINDOW BUFFER
e VIEW
em vez de LOAD TABLE AS SELECT
, SORT AGGREGATE
e TABLE ACCESS FULL
. Atualizar
-
Acabei de instalar o 11.2.0.4 (Win7/32bit) e testá-lo em relação à consulta inicial. Nada mudou no comportamento do otimizador.
-
Não há possibilidade de afetar diretamente o comportamento de um CBO, mesmo com o uso deinline
(não documentado) ouRULE
(obsoleto) dicas. Pode ser que algum Guru conheça alguma variante, mas é um Top Secret para mim (e para o Google também :-) .
-
Fazer as coisas em uma instrução de seleção em tempo razoável é possível se uma instrução de seleção principal for separada em partes e colocada na função que retorna um conjunto de linhas (função que retorna sys_refcursor ou cursor de tipo forte), mas não é uma escolha se uma consulta construído em tempo de execução.
-
A solução alternativa com o uso de XML é possível,mas essa variante parece remover uma amígdala pelo cu(desculpe):
.
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
)
)
)
)))
Outra coisa sobre um código estranho acima é que esta variante é aplicável apenas se
with
conjuntos de dados não tinham um grande número de linhas.