2013-10-24 82 views
1

我是Oracle的新手,並且已經完成了一項改進當前在基於Web的應用程序中運行的一些現有SQL查詢的任務。我提取了以下查詢並在SQL Developer中運行它以查看解釋信息。我對「計劃表輸出」並不是很熟悉,並在查詢性能方面尋求一些幫助,這些查詢性能大約需要2秒才能返回50行。性能調優現有Oracle查詢

查詢:

SELECT PATD.StageName                      AS StageName, 
    100 * (LINKS.NEVENTS - LINKS.NCONTACTS)/(DECODE(LINKS.NEVENTS,0,1,LINKS.NEVENTS))      AS PERCENTREPEAT, 
    LINKS.NEVENTS                       AS NEVENTS, 
    LINKS.NCONTACTS                       AS NCONTACTS, 
    'STAGE'                         AS DETAILLEVEL, 
    LATD.LinkClassName                      AS LINKTYPE, 
    PATD.ActivityGroupTxt                     AS PACTIVITYGROUP, 
    SATD.ActivityGroupTxt                     AS SACTIVITYGROUP 
FROM 
    (SELECT NEVENTS , 
    NCONTACTS , 
    LINKTYPEKEY , 
    PACTIVITYGROUP , 
    SACTIVITYGROUP 
    FROM 
    (SELECT SUM (
     CASE 
     WHEN CALF.PredActivityKey = -1 
     THEN 0 
     ELSE 1 
     END)        AS NEVENTS, 
     COUNT (DISTINCT CALF.RELATEDID)  AS NCONTACTS, 
     CALF.predecessorlinkclasskey  AS LINKTYPEKEY, 
     CALF.PredActivityKey    AS PACTIVITYGROUP, 
     CALF.SuccActivityKey    AS SACTIVITYGROUP 
    FROM 
     (SELECT * FROM TABLE_A WHERE GKEY = 4 
    ) CALF 
    JOIN TABLE_B DDate 
    ON (DDate.DateKey=CALF.SegmentStartACDDateKey) 
    WHERE CALF.segmentstartacddate BETWEEN TO_DATE('2012-09-25', 'YYYY-MM-DD') AND TO_DATE('2013-09-25', 'YYYY-MM-DD') 
    AND DDate.fullDate BETWEEN TO_DATE('2012-09-25', 'YYYY-MM-DD') AND TO_DATE('2013-09-25', 'YYYY-MM-DD') 
    GROUP BY CALF.predecessorlinkclasskey, 
       CALF.PredActivityKey, 
       CALF.SuccActivityKey 
    ORDER BY NEVENTS DESC 
    ) 
    WHERE ROWNUM <= 50 
) LINKS 
JOIN TABLE_C LATD 
ON (LATD.linkclasskey=LINKS.LINKTYPEKEY) 
JOIN TABLE_D PATD 
ON (PATD.cfactivitykey=LINKS.PACTIVITYGROUP) 
JOIN TABLE_D SATD 
ON (SATD.cfactivitykey=LINKS.SACTIVITYGROUP) 

計劃表輸出繼電器:

| Id | Operation        | Name     | Rows | Bytes |TempSpc| Cost (%CPU)| Time  | Pstart| Pstop |                                         
-------------------------------------------------------------------------------------------------------------------------------------------                                         
| 0 | SELECT STATEMENT      |       | 50 | 4550 |  | 54882 (1)| 00:10:59 |  |  |                                         
|* 1 | HASH JOIN        |       | 50 | 4550 |  | 54882 (1)| 00:10:59 |  |  |                                         
|* 2 | HASH JOIN        |       | 50 | 3850 |  | 54855 (1)| 00:10:59 |  |  |                                         
| 3 | MERGE JOIN       |       | 50 | 2550 |  | 54829 (1)| 00:10:58 |  |  |                                         
| 4 |  TABLE ACCESS BY INDEX ROWID   | TABLE_C     |  3 | 39 |  |  2 (0)| 00:00:01 |  |  |                                         
| 5 |  INDEX FULL SCAN     | PK_TABLE_C    |  3 |  |  |  1 (0)| 00:00:01 |  |  |                                         
|* 6 |  SORT JOIN       |       | 50 | 1900 |  | 54827 (1)| 00:10:58 |  |  |                                         
| 7 |  VIEW        |       | 50 | 1900 |  | 54826 (1)| 00:10:58 |  |  |                                         
|* 8 |  COUNT STOPKEY      |       |  |  |  |   |   |  |  |                                         
| 9 |  VIEW        |       | 1244K| 45M|  | 54826 (1)| 00:10:58 |  |  |                                         
|* 10 |   SORT ORDER BY STOPKEY   |       | 1244K| 45M| 61M| 54826 (1)| 00:10:58 |  |  |                                         
| 11 |   HASH GROUP BY     |       | 1244K| 45M| 61M| 54826 (1)| 00:10:58 |  |  |                                         
| 12 |   VIEW       | VW_DAG_0    | 1244K| 45M|  | 30184 (2)| 00:06:03 |  |  |                                         
| 13 |   HASH GROUP BY    |       | 1244K| 56M| 81M| 30184 (2)| 00:06:03 |  |  |                                         
|* 14 |    HASH JOIN     |       | 1244K| 56M|  | 15278 (2)| 00:03:04 |  |  |                                         
| 15 |    TABLE ACCESS BY INDEX ROWID| TABLE_B     | 367 | 5138 |  | 15 (0)| 00:00:01 |  |  |                                         
|* 16 |    INDEX RANGE SCAN   | AKI_TABLE_B    | 367 |  |  |  2 (0)| 00:00:01 |  |  |                                         
| 17 |    PARTITION RANGE ITERATOR |       | 1247K| 40M|  | 15253 (2)| 00:03:04 | 40 | 92 |                                         
| 18 |    PARTITION HASH ALL  |       | 1247K| 40M|  | 15253 (2)| 00:03:04 |  1 |  3 |                                         
|* 19 |    TABLE ACCESS FULL  | TABLE_A     | 1247K| 40M|  | 15253 (2)| 00:03:04 | 118 | 276 |                                         
| 20 | PARTITION LIST ALL     |       | 10183 | 258K|  | 26 (0)| 00:00:01 |  1 |  4 |                                         
| 21 |  TABLE ACCESS FULL     | TABLE_D     | 10183 | 258K|  | 26 (0)| 00:00:01 |  1 |  4 |                                         
| 22 | PARTITION LIST ALL     |       | 10183 | 139K|  | 26 (0)| 00:00:01 |  1 |  4 |                                         
| 23 | TABLE ACCESS FULL     | TABLE_D     | 10183 | 139K|  | 26 (0)| 00:00:01 |  1 |  4 |                                         
-------------------------------------------------------------------------------------------------------------------------------------------                                         

Predicate Information (identified by operation id):                                                               
---------------------------------------------------                                                               

    1 - access("SATD"."cfactivitykey"="LINKS"."SACTIVITYGROUP")                                                        
    2 - access("PATD"."cfactivitykey"="LINKS"."PACTIVITYGROUP")                                                        
    6 - access("LATD"."LINKCLASSKEY"="LINKS"."LINKTYPEKEY")                                                            
     filter("LATD"."LINKCLASSKEY"="LINKS"."LINKTYPEKEY")                                                            
    8 - filter(ROWNUM<=50)                                                                      
    10 - filter(ROWNUM<=50)                                                                      
    14 - access("DDATE"."DATEKEY"="TABLE_A"."SEGMENTSTARTACDDATEKEY")                                                         
    16 - access("DDATE"."FULLDATE">=TO_DATE(' 2012-09-25 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "DDATE"."FULLDATE"<=TO_DATE('                                             
       2013-09-25 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))                                                            
    19 - filter("GKEY"=4 AND "TABLE_A"."SEGMENTSTARTACDDATE">=TO_DATE(' 2012-09-25 00:00:00', 'syyyy-mm-dd hh24:mi:ss')                                            
       AND "TABLE_A"."SEGMENTSTARTACDDATE"<=TO_DATE(' 2013-09-25 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))                                               

Note                                                                           
-----                                                                           
    - automatic DOP: skipped because of IO calibrate statistics are missing                                                         

49 rows selected 
+0

你可以放在桌子上嗎? 爲什麼在這兩個日期之間有什麼區別? –

+0

那麼你有一些全表掃描*可能*是一個問題。這些表中有多少行? – OldProgrammer

+0

查詢選擇一年的數據。不幸的是我沒有DDL。 – user676567

回答

0

這似乎是因 '分頁' 的經典性能問題。但是,我試圖將此視爲SQL和執行計劃在這裏提供的。 如果您搜索12個月左右的大窗口(BETWEEN '2012-09-25' AND '2013-09-25'),CBO將繼續並依賴於所有關鍵表上的FTS。 但是,如果適當的分區已經到位,那可能不會那麼糟糕。 SQL可以很快返回(如果不在所需的2秒內)。

您的SQL中最昂貴的操作是計劃輸出(排序順序和GROUP BY)。

|* 10 |   SORT ORDER BY STOPKEY   |       | 1244K| 45M| 61M| 54826 (1)| 00:10:58 |  |  |                                         
| 11 |   HASH GROUP BY     |       | 1244K| 45M| 61M| 54826 (1)| 00:10:58 |  |  |                                         
| 12 |   VIEW       | VW_DAG_0    | 1244K| 45M|  | 30184 (2)| 00:06:03 |  |  |                                         
| 13 |   HASH GROUP BY    |       | 1244K| 56M| 81M| 30184 (2)| 00:06:03 |  |  |                                         

因此,我建議以下(基於解釋計劃和假設統計信息更新):

1)全球指數上 'TABLE_A' 支持昂貴的 '..GROUP BY': -

CALF.predecessorlinkclasskey, 
    CALF.PredActivityKey, 
    CALF.SuccActivityKey 

2)重新訪問分區:重新組織分區(可以是表子分區以及)(至少最大TABLE_A),包括以下內容:

表-A:在「GKEY」的「SEGMENTSTARTACDDATE」

3)縮小日期範圍窗口 子分區 分區:我也建議你重新思考和日期範圍窗口減少到更逼真和最優化的水平(可能是一個月或一個Qtr) 手中沒有任何一行要穿過1247K行50行。

4)使用GTT停放臨時輸出(你可以自己做個實驗,作爲最後的手段,但是,這將要求碼重新分解/ SQL分裂等)

您可以嘗試所有這些或部分選項。 確保您的統計信息(表格/索引)是最新的