8

Oracle 11gへのアップグレード後にOracleクエリを最適化するのに問題があり、この問題が私を少し怒らせ始めています。

簡単なテストケースを作成した後、より多くの情報が得られたため、この質問は完全に編集されていることに注意してください。元の質問はここにあります:https ://stackoverflow.com/revisions/12304320/1 。

この問題は、2つのテーブルを結合するときに、そのうちの1つがbetween日付列に条件を持っている場合、クエリがリモートテーブルに結合すると、バインドのピークが発生しないことです。

これは、問題の再現に役立つテストケースです。最初に2つのソーステーブルを設定します。1つ目は、30年前の月の最初の日付のリストです。

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
);

次に、以下から供給されたいくつかのデータdba_objects

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;

次に、空のテーブルを作成して、データを実行します。

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 dual@emirrl -- 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と、正しいカーディナリティ(2ではなく139)が得られます。

-------------------------------------------------------------------------------------
| 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のバグですか、それとも予想される動作ですか?

4

1 に答える 1

1

動的サンプリングを台無しにする必要があると思います。11g では動作が異なるため、問題の原因となる場合があります。

于 2012-09-07T12:18:34.893 に答える