2014-06-27 53 views
-9

如何提高以下查詢的性能?目前需要35分鐘。需要35分鐘的SQL查詢

-- 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 39萬行
  • RPT_FT_MD_FLOWS 145萬行

這裏是解釋命令的結果:

解釋命令

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') 
+0

感謝Chris的編輯,現在看起來很清楚 – nkalis

+7

您的連接語法是[古](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using -old-style-joins.aspx)和你**需要**來解決它。 – Zane

+0

爲什麼你需要在如此多的標準上加入2個表格? – Zane

回答

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

這裏的真正解決方案是修復表格的設計。不應該需要在8列上進行連接。 – Kermit

+0

@Kermit我非常懷疑現在還有。 – Zane

+0

您好Kermit,請您在此更詳細地介紹我 - 這裏真正的解決方案是修復表格的設計,我會將此解決方案 – nkalis

0

你可能想從開始重寫查詢

  1. 使用正常連接(內部)表之間,只包括與應用過濾器,不加入一個where子句。
  2. 看看數據庫的標準化程度如何,如果標準化程度良好,您應該能夠優化索引和統計數據以提高查詢性能。
  3. 看看可能派上用場的分區等事情。
  4. 檢查數據頁面是如何分散的,並修復如果這導致問題。