2014-06-27 2 views
-9

Comment puis-je améliorer les performances de la requête ci-dessous? Cela prend actuellement 35 minutes.Requête SQL en 35 minutes

-- 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 millions de lignes
  • RPT_FT_MD_FLOWS: 145 millions de lignes

Voici le résultat de la commande expliquer:

Expliquer Commande

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

Merci Chris pour l'édition, il semble maintenant clair – nkalis

+7

Votre syntaxe de jointure est [antique] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using -old-style-joins.aspx) et vous ** NEED ** pour le réparer. – Zane

+0

Pourquoi avez-vous besoin de joindre 2 tables sur autant de critères? – Zane

Répondre

4

D'accord pour une raison ou une autre, je vais essayer d'aider avec cette requête. Commençons donc par le nettoyer pour pouvoir l'utiliser. Tout d'abord, nous allons commencer par oblitérer le ancient join syntax. Nous ajouterons également des alias. Le crénelage est lorsque vous donnez un surnom à un titre que vous pouvez ensuite référencer partout de cette façon, nous n'encombrons pas le code avec des noms de table répétés partout. Cela nous donne quelque chose comme ça.

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 

Commençons donc par ces prédicats de jointure. Je sais que vous prétendez que ce sont des règles de gestion, mais est-ce vraiment nécessaire de réunir deux tables? Si c'est le cas, la structure de votre table est désossée. Il devrait y avoir aucune raison d'avoir 9 rejoindre des prédicats pour rassembler 2 tables. Sont-ils tous vraiment augmenter la sélectivité de la requête? Si tout cela est vraiment nécessaire, votre structure de table doit être corrigée.

Ensuite, votre table ne semble pas tirer parti des index. Si vous ne l'avez pas déjà, vous devriez avoir une sorte d'index clusterisé sur ces tables pour faciliter la recherche.

Vous souhaiterez probablement également ajouter d'autres index à cette table afin de réduire la quantité de données à analyser/rechercher pour obtenir vos résultats. Il n'y a aucune raison que votre requête devrait joindre toutes les 184 millions de lignes pour renvoyer 268 lignes.

+1

La vraie solution ici est de réparer le design des tables. Il ne devrait pas être nécessaire de faire une jointure sur 8 colonnes. – Kermit

+0

@Kermit Je doute fortement qu'il existe encore. – Zane

+0

Salut Kermit, Pourriez-vous m'expliquer davantage sur ce point - La vraie solution ici est de réparer la conception des tables, je mettrais cela à travers la solution – nkalis

0

Vous pouvez réécrire votre requête du début

  1. utilisation normale des jointures (INNER) entre les tables et ne comprennent une clause where avec des filtres appliqués qui ne sont pas rejoint. Regardez à quel point la base de données est normalisée, si elle est bien normalisée, vous devriez pouvoir optimiser vos index et statistiques pour améliorer les performances des requêtes.
  2. Regardez des choses comme le partitionnement qui pourrait être utile.
  3. Vérifiez la fragmentation des pages de données et corrigez-les si cela cause un problème.