3

私は、Oracle クエリの実行計画について少し混乱しています。これは、プラットフォーム IBM AIX 6.1 上の Oracle Enterprise Edition 11.2.0.1.0 にあります。テーブル TEST1 (100 万行) と別のテーブル TEST2 (50,000 行) があります。両方のテーブルに同一の列があります。これら 2 つのテーブルの結合として作成されたビューがあります。WHERE 句にインデックス付きの列を使用して、このビューでクエリを実行しています。私が見つけたのは、インデックスが使用されておらず、テーブル全体のスキャンが行われていることです。クエリを少し変更して、インデックスの使用を開始しました。この特定の変更がどのように計画の変更につながるのか疑問に思っています.

以下の完全な DDL + DML を見つけてください。簡単な例を挙げました。実際のスキーマと要件はもう少し複雑です。実際、問題の問合せはOCIコード・ジェネレータによって動的に構築および実行されます。ここでの私の意図は、代替案を入手することではなく、計画変更の背後にある論理的な理由を実際に理解することです (つまり、私はアプリケーション プログラマーであり、データベース管理者ではありません)。あなたの助けに感謝します。

DROP TABLE TEST1 CASCADE CONSTRAINTS ;  
DROP TABLE TEST2 CASCADE CONSTRAINTS ;  

CREATE TABLE TEST1  
(  
    ID      NUMBER(20)     NOT NULL,  
    NAME    VARCHAR2(40),  
    DAY     NUMBER(20)  
)  
PARTITION BY RANGE (DAY)  
(  
    PARTITION P001 VALUES LESS THAN (2),  
    PARTITION P002 VALUES LESS THAN (3),  
    PARTITION P003 VALUES LESS THAN (4),  
    PARTITION P004 VALUES LESS THAN (5),  
    PARTITION P005 VALUES LESS THAN (6),  
    PARTITION P006 VALUES LESS THAN (7),  
    PARTITION P007 VALUES LESS THAN (8),  
    PARTITION P008 VALUES LESS THAN (9),  
    PARTITION P009 VALUES LESS THAN (10),  
    PARTITION P010 VALUES LESS THAN (11),  
    PARTITION P011 VALUES LESS THAN (12),  
    PARTITION P012 VALUES LESS THAN (13),  
    PARTITION P013 VALUES LESS THAN (14),  
    PARTITION P014 VALUES LESS THAN (15),  
    PARTITION P015 VALUES LESS THAN (16),  
    PARTITION P016 VALUES LESS THAN (17),  
    PARTITION P017 VALUES LESS THAN (18),  
    PARTITION P018 VALUES LESS THAN (19),  
    PARTITION P019 VALUES LESS THAN (20),  
    PARTITION P020 VALUES LESS THAN (21),  
    PARTITION P021 VALUES LESS THAN (22),  
    PARTITION P022 VALUES LESS THAN (23),  
    PARTITION P023 VALUES LESS THAN (24),  
    PARTITION P024 VALUES LESS THAN (25),  
    PARTITION P025 VALUES LESS THAN (26),  
    PARTITION P026 VALUES LESS THAN (27),  
    PARTITION P027 VALUES LESS THAN (28),  
    PARTITION P028 VALUES LESS THAN (29),  
    PARTITION P029 VALUES LESS THAN (30),  
    PARTITION P030 VALUES LESS THAN (31)  
) ;  

CREATE INDEX IX_ID on TEST1 (ID) INITRANS 4 STORAGE(FREELISTS 16) LOCAL  
(  
    PARTITION P001,  
    PARTITION P002,  
    PARTITION P003,  
    PARTITION P004,  
    PARTITION P005,  
    PARTITION P006,  
    PARTITION P007,  
    PARTITION P008,  
    PARTITION P009,  
    PARTITION P010,  
    PARTITION P011,  
    PARTITION P012,  
    PARTITION P013,  
    PARTITION P014,  
    PARTITION P015,  
    PARTITION P016,  
    PARTITION P017,  
    PARTITION P018,  
    PARTITION P019,  
    PARTITION P020,  
    PARTITION P021,  
    PARTITION P022,  
    PARTITION P023,  
    PARTITION P024,  
    PARTITION P025,  
    PARTITION P026,  
    PARTITION P027,  
    PARTITION P028,  
    PARTITION P029,  
    PARTITION P030  
) ;  

CREATE TABLE TEST2  
(  
    ID      NUMBER(20)      PRIMARY KEY   NOT NULL,  
    NAME    VARCHAR2(40),  
    DAY     NUMBER(20)  
) ;  

CREATE OR REPLACE VIEW TEST_V AS  
SELECT  
    ID, NAME, DAY  
FROM  
    TEST1  
UNION  
SELECT  
    ID, NAME, DAY  
FROM  
    TEST2 ;  

begin  
    for count in 1..1000000  
    loop  
        insert into test1 values(count, 'John', mod(count, 30) + 1) ;  
    end loop ;  
end ;  
/  

begin  
    for count in 1000000..1050000  
    loop  
        insert into test2 values(count, 'Mary', mod(count, 30) + 1) ;  
    end loop ;  
end ;  
/  

commit ;  

set lines 300 ;  
set pages 1000 ;  

-- Actual query  
explain plan for  
    SELECT Key FROM  
    (  
        WITH recs AS  
        (  
            SELECT * FROM TEST_V WHERE ID = 70000  
        )  
        (  
            SELECT 1 AS Key FROM recs WHERE NAME = 'John'  
        )  
        UNION  
        (  
            SELECT 2 AS Key FROM recs WHERE NAME = 'Mary'  
        )  
    ) ;  

select * from table(dbms_xplan.display()) ;  

PLAN_TABLE_OUTPUT  
------------------------------------------------------------------------------------------------------------------------------------------  
| Id  | Operation                   | Name                         | Rows  | Bytes  | TempSpc | Cost (%CPU)  |    Time  | Pstart | Pstop |  
------------------------------------------------------------------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT            |                              | 1611K | 4721K  |         |   13559 (1)  | 00:02:43 |        |       |  
|   1 |  VIEW                       |                              | 1611K | 4721K  |         |   13559 (1)  | 00:02:43 |        |       |  
|   2 |   TEMP TABLE TRANSFORMATION |                              |       |        |         |              |          |        |       |  
|   3 |    LOAD AS SELECT           | SYS_TEMP_0FD9D6610_34D3B6C   |       |        |         |              |          |        |       |  
|*  4 |     VIEW                    | TEST_V                       | 805K  | 36M    |         |   10403 (1)  | 00:02:05 |        |       |  
|   5 |      SORT UNIQUE            |                              | 805K  | 36M    |   46M   |   10403 (8)  | 00:02:05 |        |       |  
|   6 |       UNION-ALL             |                              |       |        |         |              |          |        |       |  
|   7 |        PARTITION RANGE ALL  |                              | 752K  | 34M    |         |   721 (1)    | 00:00:09 |    1   |   30  |  
|   8 |     TABLE ACCESS FULL       | TEST1                        | 752K  | 34M    |         |   721 (1)    | 00:00:09 |    1   |   30  |  
|   9 |        TABLE ACCESS FULL    | TEST2                        | 53262 | 2496K  |         |   68 (0)     | 00:00:01 |        |       |  
|  10 |    SORT UNIQUE              |                              | 1611K | 33M    |   43M   |   13559 (51) | 00:02:43 |        |       |  
|  11 |     UNION-ALL               |                              |       |        |         |              |          |        |       |  
|* 12 |      VIEW                   |                              | 805K  | 16M    |         |   1429 (1)   | 00:00:18 |        |       |  
|  13 |       TABLE ACCESS FULL     | SYS_TEMP_0FD9D6610_34D3B6C   | 805K  | 36M    |         |   1429 (1)   | 00:00:18 |        |       |  
|* 14 |      VIEW                   |                              | 805K  | 16M    |         |   1429 (1)   | 00:00:18 |        |       |  
|  15 |       TABLE ACCESS FULL     | SYS_TEMP_0FD9D6610_34D3B6C   | 805K  | 36M    |         |   1429 (1)   | 00:00:18 |        |       |  
------------------------------------------------------------------------------------------------------------------------------------------  

Predicate Information (identified by operation id):  
---------------------------------------------------  
   4 - filter("ID"=70000)  
  12 - filter("NAME"='John')  
  14 - filter("NAME"='Mary')  


-- Modified query (only change is absence of outermost SELECT)  
explain plan for  
    WITH recs AS  
    (  
        SELECT * FROM TEST_V WHERE ID = 70000  
    )  
    (  
        SELECT 1 AS Key FROM recs WHERE NAME = 'John'  
    )  
    UNION  
    (  
        SELECT 2 AS Key FROM recs WHERE NAME = 'Mary'  
    ) ;  

select * from table(dbms_xplan.display()) ;  

PLAN_TABLE_OUTPUT  
-----------------------------------------------------------------------------------------------------------------------------------------  
| Id  | Operation                                | Name                       | Rows  | Bytes | Cost (%CPU) | Time     | Pstart | Pstop |  
-----------------------------------------------------------------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT                         |                            |   4   |  88   |    6 (67)   | 00:00:01 |        |       |  
|   1 |  TEMP TABLE TRANSFORMATION               |                            |       |       |             |          |        |       |  
|   2 |   LOAD AS SELECT                         | SYS_TEMP_0FD9D6611_34D3B6C |       |       |             |          |        |       |  
|   3 |    VIEW                                  | TEST_V                     |   2   |  96   |    4 (50)   | 00:00:01 |        |       |  
|   4 |     SORT UNIQUE                          |                            |   2   |  96   |    4 (75)   | 00:00:01 |        |       |  
|   5 |      UNION-ALL                           |                            |       |       |             |          |        |       |  
|   6 |       PARTITION RANGE ALL                |                            |   1   |  48   |    1 (0)    | 00:00:01 |    1   |   30  |  
|   7 |        TABLE ACCESS BY LOCAL INDEX ROWID | TEST1                      |   1   |  48   |    1 (0)    | 00:00:01 |    1   |   30  |  
|*  8 |     INDEX RANGE SCAN                     | IX_ID                      |   1   |       |    1 (0)    | 00:00:01 |    1   |   30  |  
|   9 |       TABLE ACCESS BY INDEX ROWID        | TEST2                      |   1   |  48   |    1 (0)    | 00:00:01 |        |       |  
|* 10 |        INDEX UNIQUE SCAN                 | SYS_C001242692             |   1   |       |    1 (0)    | 00:00:01 |        |       |  
|  11 |   SORT UNIQUE                            |                            |   4   |  88   |    6 (67)   | 00:00:01 |        |       |  
|  12 |    UNION-ALL                             |                            |       |       |             |          |        |       |  
|* 13 |     VIEW                                 |                            |   2   |  44   |    2 (0)    | 00:00:01 |        |       |  
|  14 |      TABLE ACCESS FULL                   | SYS_TEMP_0FD9D6611_34D3B6C |   2   |  96   |    2 (0)    | 00:00:01 |        |       |  
|* 15 |     VIEW                                 |                            |   2   |  44   |    2 (0)    | 00:00:01 |        |       |  
|  16 |      TABLE ACCESS FULL                   | SYS_TEMP_0FD9D6611_34D3B6C |   2   |  96   |    2 (0)    | 00:00:01 |        |       |  
-----------------------------------------------------------------------------------------------------------------------------------------  

Predicate Information (identified by operation id):  
---------------------------------------------------  
   8 - access("ID"=70000)  
  10 - access("ID"=70000)  
  13 - filter("NAME"='John')  
  15 - filter("NAME"='Mary')  

quit ;  

よろしくお願いします、
Reji

4

1 に答える 1

2

これを 11.2.0.3 で再現することはできません。この動作の論理的な説明は、11.2.0.3 で明らかに解決されたバグに遭遇したこと以外にはないと思います。

私の目にすぐに飛びついたことの 1 つは、オブジェクト統計の欠如と、出力が完全である場合、OPTIMIZER_DYNAMIC_SAMPLING が 0 に設定されているという事実です。OPTIMIZER_DYNAMIC_SAMPLING=2 で再現を試みることができます。その場合、オブジェクト統計が欠落している場合、動的サンプラーが作動します。ところで:正しいオプティマイザ統計の代わりにこの機能を使用しないでください。ダイナミック サンプリングの詳細ダイナミック サンプリングとそのオプティマイザーへの影響

あなたの-素敵な文書化-質問とスクリプト/テストケースでは、追加とログなしを利用しようとしています。これは、値を含む行の挿入ではなく、一括挿入でのみ機能します。何が起こるかは、すべての挿入で発生します。ハイウォーターマークを押し上げ、フリーブロックにデータの完全なブロックをダンプします。この場合、1行しかありません....幸い、データベースはこの命令を無視します。

テーブルに対して SQL を実行する前に、必ずオプティマイザー統計を与えてください。これは確かにあなたのケースに役立ちます。

于 2012-09-10T12:09:27.987 に答える