簡體   English   中英

Oracle查詢執行計划

[英]Oracle query execution plan

我對Oracle查詢的執行計划感到困惑。 這是在IBM AIX 6.1平台上的Oracle Enterprise Edition 11.2.0.1.0中。 我有一個表TEST1(100萬行)和另一個表TEST2(50,000行)。 兩個表都有相同的列。 有一個視圖被創建為這兩個表的聯合。 我在這個視圖上觸發了一個查詢,在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

我無法在11.2.0.3中重現這一點,我不認為除了這個行為之外還有一個邏輯解釋:你遇到了一個bug,這顯然是在11.2.0.3中解決的。

我眼中立即跳出的一件事是缺少對象統計數據 - 如果輸出完成 - OPTIMIZER_DYNAMIC_SAMPLING設置為0.您可以嘗試使用OPTIMIZER_DYNAMIC_SAMPLING = 2重現。 在這種情況下,如果缺少對象統計信息,動態采樣器將啟動。 順便說一句:不要使用此功能而不是正確的優化程序統計信息。 有關動態采樣的更多信息動態采樣及其對優化器的影響

在您的 - 很好的文檔 - 問題和腳本/測試用例中,您嘗試使用append和nologging。 這僅適用於批量插入,不適用於具有值的行插入。 會發生什么事情對於每個插入:推高高水位標記並在空閑塊中轉儲完整的數據塊,在你的情況下只有1行....幸運的是,數據庫忽略了這條指令。

在將SQL發送到表之前,請確保為其提供優化程序統計信息。 這肯定會對你的情況有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM