Q1:計算時間については何もないようです。最適化アルゴリズムのバグが原因で、最適な実行プランを計算しているときに問題が発生します。
Q2:Oracle 11.X.0.Xには、ネストされたクエリの最適化とクエリの因数分解に関連する既知の修正済みのバグがいくつかあります。しかし、具体的な問題を見つけるのは非常に困難です。
Q3:文書化されていないが2つあります ヒント:materialize
およびinline
しかし、私があなたの例を試している間、それらのどれも私のために働きません。サーバー構成の一部の変更または11.2.0.3へのアップグレードにより、ネストされたwith
の制限が増える可能性があります。 句:私(11.2.0.3 Win7 / x86)の場合、例は正常に機能しますが、ネストされたテーブルの数を30に増やすと、セッションがハングします。
回避策は次のようになります:
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
)
少なくとも、ネストレベル30で機能し、WINDOW BUFFER
を使用してまったく異なる実行プランを生成します。 およびVIEW
LOAD TABLE AS SELECT
の代わりに 、SORT AGGREGATE
およびTABLE ACCESS FULL
。
更新
-
11.2.0.4(Win7 / 32ビット)をインストールし、最初のクエリに対してテストします。オプティマイザの動作に変更はありません。
-
inline
を使用しても、CBOの動作に直接影響を与える可能性はありません。 (文書化されていない)またはRULE
(非推奨)ヒント。いくつかの教祖がいくつかの変種を知っているかもしれませんが、それは私にとって(そしてGoogleも:-)トップシークレットです。 -
メインのselectステートメントがパーツに分割され、行のセットを返す関数(sys_refcursorまたは強い型のカーソルを返す関数)に配置されている場合、1つのselectステートメントで適切な時間内に処理を実行できますが、クエリの場合は選択できません。実行時に構築されます。
-
XMLの使用による回避策は可能ですが、
このバリアントはお尻の穴から扁桃腺を取り除くように見えます(申し訳ありません):
。
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
)
)
)
)))
上記の奇妙なコードに関するもう1つの点は、このバリアントはwith
の場合にのみ適用できるということです。 データセットには大きな行数はありませんでした。