Oracle 11gへのアップグレード後にOracleクエリを最適化する際に問題が発生しています。この問題が少し怒っています。分散クエリでバインドのピークが無効になっていますか?
簡単なテストケースを作成した後でさらに詳しい情報があるので、この質問は完全に編集されました。最初の質問はhttps://stackoverflow.com/revisions/12304320/1です。
この問題は、2つのテーブルを結合するときに、そのうちの1つが日付列にbetween
の条件を持つ場合、クエリがリモートテーブルに結合するとバインドのピークが発生しないという問題があります。
問題を再現するのに役立つテストケースです。最初に2つのソーステーブルを設定します。
create table mike_temp_dba_objects as
select owner, object_name, subobject_name, object_id, created
from dba_objects
union all
select owner, object_name, subobject_name, object_id, created
from dba_objects;
その後でデータを実行するために、空のテーブルを作成します。最初は、その後dba_objects
から調達し、一部のデータが
create table mike_temp_etl_control
as
select
add_months(trunc(sysdate, 'MM'), 1-row_count) as reporting_date
from (
select level as row_count
from dual
connect by level < 360
);
30年遡る、月の最初のもの、日付のリストですto:
create table mike_temp_1
as
select
a.OWNER,
a.OBJECT_NAME,
a.SUBOBJECT_NAME,
a.OBJECT_ID,
a.CREATED,
b.REPORTING_DATE
from
mike_temp_dba_objects a
join mike_temp_etl_control b on (
b.reporting_date between add_months(a.created, -24) and a.created)
where 1=2;
次にコードを実行します。クエリを遅くする(または実行計画を取得するために他の方法を使用する)には、より大きなバージョンのmike_temp_dba_objectsを作成する必要があります。クエリが実行されている間、別のセッションからselect * from table(dbms_xplan.display_cursor(sql_id => 'xxxxxxxxxxx'))
を実行して、セッションから実行計画を取得します。
declare
pv_report_start_date date := date '2002-01-01';
v_report_end_date date := date '2012-07-01';
begin
INSERT /*+ APPEND */
INTO mike_temp_5
select
a.OWNER,
a.OBJECT_NAME,
a.SUBOBJECT_NAME,
a.OBJECT_ID,
a.CREATED,
b.REPORTING_DATE
from
mike_temp_dba_objects a
join mike_temp_etl_control b on (
b.reporting_date between add_months(a.created, -24) and a.created)
cross join [email protected] -- This line causes problems...
where
b.reporting_date between add_months(pv_report_start_date, -12) and v_report_end_date;
rollback;
end;
クエリでリモートテーブルを有することにより、mike_temp_etl_controlテーブルの基数の見積もりは完全に間違っているとバインドチラッと覗くが起こっていないようです。
上記のクエリの実行プランを以下に示します。
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | | | 373 (100)|
| 1 | LOAD AS SELECT | | | | |
|* 2 | FILTER | | | | |
| 3 | MERGE JOIN | | 5 | 655 | 373 (21)|
| 4 | SORT JOIN | | 1096 | 130K| 370 (20)|
| 5 | MERGE JOIN CARTESIAN| | 1096 | 130K| 369 (20)|
| 6 | REMOTE | DUAL | 1 | | 2 (0)|
| 7 | BUFFER SORT | | 1096 | 130K| 367 (20)|
|* 8 | TABLE ACCESS FULL | MIKE_TEMP_DBA_OBJECTS | 1096 | 130K| 367 (20)|
|* 9 | FILTER | | | | |
|* 10 | SORT JOIN | | 2 | 18 | 3 (34)|
|* 11 | TABLE ACCESS FULL | MIKE_TEMP_ETL_CONTROL | 2 | 18 | 2 (0)|
---------------------------------------------------------------------------------------
私はその後、ローカルバージョンとリモートdual
を交換した場合、私が正しいカーディナリティ(139の代わりに、2)を取得:
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | | | 10682 (100)|
| 1 | LOAD AS SELECT | | | | |
|* 2 | FILTER | | | | |
| 3 | MERGE JOIN | | 152K| 19M| 10682 (3)|
| 4 | SORT JOIN | | 438K| 51M| 10632 (2)|
| 5 | NESTED LOOPS | | 438K| 51M| 369 (20)|
| 6 | FAST DUAL | | 1 | | 2 (0)|
|* 7 | TABLE ACCESS FULL| MIKE_TEMP_DBA_OBJECTS | 438K| 51M| 367 (20)|
|* 8 | FILTER | | | | |
|* 9 | SORT JOIN | | 139 | 1251 | 3 (34)|
|* 10 | TABLE ACCESS FULL| MIKE_TEMP_ETL_CONTROL | 139 | 1251 | 2 (0)|
-------------------------------------------------------------------------------------
を
したがって、正しい基数をどのように見積もることができるのかという疑問はありますか?これはOracleのバグですか、これが予期される動作ですか?
簡単なものを取り除くために、[統計](http://docs.oracle.com/cd/E11882_01/server.112/e25494/general002.htm#ADMIN11525)をテーブルに集めましたか? – Ben
はい、統計はすべて新鮮でなければなりません。明日もそれを確認します。それはデータウェアハウスのETL負荷の一部であり、状況に応じてすべての情報が収集されています –
"_optim_peek_user_binds"パラメータをfalseに設定することを含むワークラウンドを持つバージョン> 11.1のバグがあります。これはオプティマイザに影響する可能性がありますが、正確にはわかりません。このパラメータがtrueまたはfalseに設定されているかどうかを確認することができます。このバグにより、ORA-3137エラーが発生します。 – Gisli