2013-10-24 3 views
1

Я новичок в Oracle и мне поставлена ​​задача улучшить некоторые существующие SQL-запросы, запущенные в настоящее время в веб-приложении. Я извлек следующий запрос и запустил его в SQL Developer для просмотра информации Explain. Я не очень хорошо знаком с выводом Plan Table и искал некоторую помощь с возможными улучшениями в производительности запросов, которая занимает около 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) 

план Таблица Ouput:

| 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 - это нет 10 & 13 выхода плана (СОРТИРОВАТЬ ЗАКАЗ и ГРУППА 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 |  |  |                                         

Поэтому я бы рекомендовал следующий (на основе объяснения плана и предполагающий STATS обновляется):

1) Глобального индекс на 'TABLE_A', чтобы поддержать дорогостоящую '..GROUP BY': -

CALF.predecessorlinkclasskey, 
    CALF.PredActivityKey, 
    CALF.SuccActivityKey 

2) Re-посещения Перегородка: реорганизовать разделы (может быть суб-разделы, а) на столе (по крайней мере по величине TABLE_A) включить следующее:

TABLE_A: раздел на «клавишу G» югу раздела на «SEGMENTSTARTACDDATE»

3) Сократить окно диапазон дат: Я также хотел бы предложить вам переосмыслить и уменьшить окно диапазона дат к более реалистичный и оптимальный уровень (может быть месяц или Qtr) Нет точки, пересекающей 1247K строк для 50 строк в руке.

4) Использование GTT парковать промежуточный выход (Вы можете экспериментировать с ним, как в крайнем случае. Но это потребует код рефакторинга/SQL расщеплению и т.д.)

Вы можете попробовать все или некоторые из них опции. Убедитесь, что ваша статистика (таблица/индекс) обновлена ​​до.

Смежные вопросы