简体   繁体   English

性能调整现有的Oracle查询

[英]Performance Tuning an Existing Oracle Query

I'm a newbie to Oracle and have been given a task of improving some existing SQL queries currently running in a web based application. 我是Oracle的新手,已获得改善当前在基于Web的应用程序中运行的某些现有SQL查询的任务。 I've extracted the following query and ran it in SQL Developer to view the Explain information. 我提取了以下查询,并在SQL Developer中运行了该查询以查看Explain信息。 I'm not very familiar with the Plan Table Output and looking for some help with possible improvements in the queries performance which takes about 2 seconds to return 50 rows. 我对计划表输出并不十分熟悉,并希望对查询性能的可能改进有所帮助,这需要大约2秒才能返回50行。

Query: 查询:

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)

Plan Table 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 

This seems to be classic performance issue arising out of 'pagination'. 这似乎是“分页”引起的经典性能问题。 But, i tempted to look into this as SQL and execution plan were provided here. 但是,由于这里提供了SQL和执行计划,因此我很想对此进行研究。 If you search for large window like 12 months or so ( BETWEEN '2012-09-25' AND '2013-09-25' ), CBO is going follow and rely on FTS on all key tables. 如果您搜索BETWEEN '2012-09-25' AND '2013-09-25' 12个月左右的大窗口( BETWEEN '2012-09-25' AND '2013-09-25' ),CBO就会遵循并依赖于所有键表上的FTS。 But, That may not that bad if proper partitions are in place. 但是,如果适当的分区到位,那可能还不错。 SQL can returns pretty fast (if not in desired 2 sec). SQL可以很快返回(如果不是在2秒钟之内)。

You most costly operations of your SQL is No 10 & 13 of plan output (SORT ORDER and GROUP BY ). 您对SQL进行的最昂贵的操作是计划输出(SORT ORDER和GROUP BY)的第10和13号。

|* 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 |       |       |                                                                                                                                                                  

Therefore, i would recommend the following (based on explain plan and assuming STATS are updated) : 因此,我将建议以下内容(基于解释计划并假定更新了STATS):

1) Global Index on 'TABLE_A' to support costly '..GROUP BY':- 1)'TABLE_A'的全球索引以支持昂贵的'..GROUP BY':-

  CALF.predecessorlinkclasskey,
  CALF.PredActivityKey,
  CALF.SuccActivityKey

2) Re-visit Partitions : re-organize partitions (may be sub-partitions as well) on table (at least largest TABLE_A) to include the following: 2) 重新访问分区 :重新组织表(至少最大的TABLE_A)上的分区(也可以是子分区)以包括以下内容:

Table_A: partition on "GKEY" sub-partition on "SEGMENTSTARTACDDATE" Table_A:“ SEGMENTSTARTACDDATE”上“ GKEY”子分区上的分区

3) Reduce the date range window : I would also suggest you re-think and reduce the date range window to a more realistic and optimal level (may be a month or a Qtr) There is no point traversing 1247K rows for 50 rows in hand. 3) 缩小日期范围窗口 :我也建议您重新考虑一下,并将日期范围窗口缩小到一个更现实和最佳的水平(可能是一个月或Qtr)。手数50行没有点遍历1247K行。

4) Use GTT to park the interim output (You can experiment with it as a last resort. But, this will demand code re-factoring/ SQL splitting etc) 4)使用GTT暂存临时输出(您可以尝试使用它作为最后的选择。但是,这将需要代码重构/ SQL拆分等)

You may try all OR some of these options. 您可以尝试全部或其中一些选项。 Make sure your stats (table/index) are up-to-update . 确保您的统计信息(表格/索引)是最新的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM