SQL查询需要35分钟

时间:2014-06-27 14:04:27

标签: sql query-performance

如何改善以下查询的效果?目前需要35分钟。

-- Select    
SELECT   
    RPT_FT_MD_FLOWS.FECDATA,  RPT_FT_MC_CONTR.L2V,  
    RPT_FT_MD_FLOWS.CODCONT, SUM(RPT_FT_MD_FLOWS.IMPMOCMP) 
FROM  
    RPT_FT_MD_FLOWS,
    RPT_FT_MC_CONTR     
WHERE    
    -- joins
    RPT_FT_MD_FLOWS.IDGRUEMP = RPT_FT_MC_CONTR.IDGRUEMP AND 
    RPT_FT_MD_FLOWS.FECDATA  = RPT_FT_MC_CONTR.FECDATA AND 
    RPT_FT_MD_FLOWS.CODCONT  = RPT_FT_MC_CONTR.CODCONT AND 
    RPT_FT_MD_FLOWS.IDEMPR   = RPT_FT_MC_CONTR.IDEMPR AND 
    RPT_FT_MD_FLOWS.IDCENT   = RPT_FT_MC_CONTR.IDCENT AND 
    RPT_FT_MD_FLOWS.CODPROD  = RPT_FT_MC_CONTR.CODPROD AND 
    RPT_FT_MD_FLOWS.IDCONTR  = RPT_FT_MC_CONTR.IDCONTR AND 
    RPT_FT_MD_FLOWS.IDSCONTR = RPT_FT_MC_CONTR.IDSCONTR AND
    -- filters
    RPT_FT_MD_FLOWS.FECDATA  = '31-May-2014' AND
    RPT_FT_MD_FLOWS.IDGRUEMP = '0022' AND
    RPT_FT_MD_FLOWS.ACUMTEMP = 'MTH' AND  
    RPT_FT_MD_FLOWS.IDESCENA = '01' AND
    RPT_FT_MD_FLOWS.CODCONT='CCPP' 
--group by 
GROUP BY 
    RPT_FT_MD_FLOWS.FECDATA,
    RPT_FT_MC_CONTR.L2V,
    RPT_FT_MD_FLOWS.CODCONT
  • RPT_FT_MC_CONTR:3900万行
  • RPT_FT_MD_FLOWS:1.45亿行

以下是explain命令的结果:

解释命令

Execution Plan
----------------------------------------------------------
Plan hash value: 2459895390

------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name            | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |                 |   268 | 29212 | 30846   (8)| 00:09:16 |       |       |        |      |            |
|   1 |  PX COORDINATOR                 |                 |       |       |            |          |       |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)           | :TQ10002        |   268 | 29212 | 30846   (8)| 00:09:16 |       |       |  Q1,02 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY                |                 |   268 | 29212 | 30846   (8)| 00:09:16 |       |       |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE                  |                 |   268 | 29212 | 30846   (8)| 00:09:16 |       |       |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH               | :TQ10001        |   268 | 29212 | 30846   (8)| 00:09:16 |       |       |  Q1,01 | P->P | HASH       |
|   6 |       HASH GROUP BY             |                 |   268 | 29212 | 30846   (8)| 00:09:16 |       |       |  Q1,01 | PCWP |            |
|*  7 |        HASH JOIN                |                 |    39M|  4127M| 30586   (7)| 00:09:11 |       |       |  Q1,01 | PCWP |            |
|   8 |         PX BLOCK ITERATOR       |                 |    39M|  1893M| 10659   (4)| 00:03:12 |     1 |    16 |  Q1,01 | PCWC |            |
|*  9 |          TABLE ACCESS FULL      | RPT_FT_MC_CONTR |    39M|  1893M| 10659   (4)| 00:03:12 |   833 |   848 |  Q1,01 | PCWP |            |
|  10 |         PX RECEIVE              |                 |   145M|  8184M| 19806   (9)| 00:05:57 |       |       |  Q1,01 | PCWP |            |
|  11 |          PX SEND BROADCAST LOCAL| :TQ10000        |   145M|  8184M| 19806   (9)| 00:05:57 |       |       |  Q1,00 | P->P | BCST LOCAL |
|  12 |           PX BLOCK ITERATOR     |                 |   145M|  8184M| 19806   (9)| 00:05:57 |    66 |    66 |  Q1,00 | PCWC |            |
|* 13 |            TABLE ACCESS FULL    | RPT_FT_MD_FLOWS |   145M|  8184M| 19806   (9)| 00:05:57 |    66 |    66 |  Q1,00 | PCWP |            |
------------------------------------------------------------------------------------------------------------------------------------------------

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

   7 - access("RPT_FT_MD_FLOWS"."CODCONT"="RPT_FT_MC_CONTR"."CODCONT" AND "RPT_FT_MD_FLOWS"."FECDATA"="RPT_FT_MC_CONTR"."FECDATA" AND
              "RPT_FT_MD_FLOWS"."IDGRUEMP"="RPT_FT_MC_CONTR"."IDGRUEMP" AND "RPT_FT_MD_FLOWS"."IDEMPR"="RPT_FT_MC_CONTR"."IDEMPR" AND
              "RPT_FT_MD_FLOWS"."IDCENT"="RPT_FT_MC_CONTR"."IDCENT" AND "RPT_FT_MD_FLOWS"."CODPROD"="RPT_FT_MC_CONTR"."CODPROD" AND
              "RPT_FT_MD_FLOWS"."IDCONTR"="RPT_FT_MC_CONTR"."IDCONTR" AND "RPT_FT_MD_FLOWS"."IDSCONTR"="RPT_FT_MC_CONTR"."IDSCONTR")
   9 - filter("RPT_FT_MC_CONTR"."IDGRUEMP"='0022' AND "RPT_FT_MC_CONTR"."FECDATA"=TO_DATE(' 2014-05-31 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss'))
  13 - filter("RPT_FT_MD_FLOWS"."IDESCENA"='01' AND "RPT_FT_MD_FLOWS"."FECDATA"=TO_DATE(' 2014-05-31 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss') AND "RPT_FT_MD_FLOWS"."IDGRUEMP"='0022' AND "RPT_FT_MD_FLOWS"."ACUMTEMP"='MTH')

2 个答案:

答案 0 :(得分:4)

好吧,由于某种原因,我将尝试帮助解决此问题。因此,我们首先将其清理干净,以便可以使用它。首先,我们将首先删除ancient join syntax。我们还会添加一些别名。别名就是当你给一个标题一个昵称,然后你可以在那里引用我们不会在任何地方重复使用重复的表名来混淆代码的地方。这给了我们这样的东西。

SELECT   
    F.FECDATA,  
    C.L2V,  
    F.CODCONT, 
    SUM(F.IMPMOCMP) 
FROM RPT_FT_MD_FLOWS as F
INNER JOIN RPT_FT_MC_CONTR as C
    ON F.IDGRUEMP = C.IDGRUEMP  
    AND F.FECDATA  = C.FECDATA  
    AND F.CODCONT  = C.CODCONT  
    AND F.IDEMPR   = C.IDEMPR  
    AND F.IDCENT   = C.IDCENT  
    AND F.CODPROD  = C.CODPROD  
    AND F.IDCONTR  = C.IDCONTR  
    AND F.IDSCONTR = C.IDSCONTR 
WHERE F.FECDATA  = '31-May-2014' 
    AND F.IDGRUEMP = '0022' 
    AND F.ACUMTEMP = 'MTH'   
    AND F.IDESCENA = '01' 
    AND F.CODCONT='CCPP' 
GROUP BY 
    F.FECDATA,
    C.L2V,
    F.CODCONT

所以让我们从这些连接谓词开始。我知道你声称这些是业务规则,但这两个表连接在一起真的是必要的吗?如果它比你的桌子结构骨架。没有理由让9个连接谓词将2个表组合在一起。它们是否真正提高了查询的选择性?如果真的需要这个,那么你的表结构需要修复。

接下来你的表似乎没有利用任何索引。如果您还没有这个,那么您应该在这些表上使用某种聚簇索引来简化搜索。

您可能还想在此表中添加一些其他索引,以帮助减少扫描/搜索以获取结果所需的大量数据。您的查询没有必要连接所有1.84亿行以返回268行。

答案 1 :(得分:0)

您可能想要从开始重写查询

  1. 在表之间使用常规联接(INNER),并且只包含应用了不是联接的过滤器的where子句。
  2. 查看数据库的规范化程度,如果规范化,则应该能够优化索引和统计信息,以提高查询性能。
  3. 看看像分区这样可以派上用场的东西。
  4. 检查数据页面的碎片程度,并在发生问题时修复它。