Bonjour à tous,
J'ai besoin d'un peu d'aide pour l'optimisation de la requête ci-dessous
Contexte :
Table Dimension Produit : D_PRODUCT
Table Dimension Temps : D_TIME (granularité au mois)
Table Dimension Account : D_ACCOUNT
Table faits : F_SALES
Je n'ai des records dans Sales que s'il y a eu effectivement une vente pour un produit / time / Account. Utilisant Tableau (outil BI), je dois "recréer artificiellement" les records pour lesquels il n'y a pas de vente, de sorte à pouvoir faire ce que je veux faire sous Tableau, d'où l'utilisation de CROSS JOIN pour obtenir un record par Product / Time / Account (et les mettre à '0' s'il n'y a pas eu de vente). Forcément, je ne m'attends pas à ce que la requête mette 2 seconde à s’exécuter, mais je pense (j'espère) qu'il est possible de faire mieux que mes 45 minutes+ d'execution. J'ai essayé de restreindre la quantité de données dans mes CROSS JOIN (avec des sous-requêtes sur D_TIME notamment en passant les filtres dans une sous-requête), mais j'ai 'l'impression' que cela augmente le temps d’exécution.
Volumétrie :
Dimension Produit : 15 000 records
Dimension Temps : 250 records si je prends tout. 48 records si j'applique mes filtres dans une sous-requête dans le cross join (mais comme je le disais j'ai l'impression que ça met encore plus de temps - je me trompe peut être)
Dimension Account : 200 records
Fait Sales : 500 000 records. 260 000 records avec le filtre appliqué pour récupérer les données des 48 derniers mois.
Logique:
Je CROSS JOIN ma D_PRODUCT à ma D_TIME et à ma D_ACCOUNT (j'ai donc une ligne par produit / temps / Account), en orange ci-dessous. Et je Left Join avec mes Sales (en vert ci-dessous).
Requête :
Merci beaucoup !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 CREATE OR REPLACE FORCE VIEW MaVue ( NET_SALES, ACCOUNT, PRODUCT, YEAR_MONTH, -- Format YYYY-MM YEAR_MONTH_DATE_FORMAT, GROSS_SALES ) AS SELECT COALESCE (SUM (sub_sales.sub_sum_netsales), 0) AS sum_netsales, subquery.ACCOUNT, subquery.PRODUCT, subquery.YEAR_MONTH, TO_DATE (subquery.YEAR_MONTH, 'YYYY-MM'), COALESCE (SUM (sub_sales.sub_sum_gross), 0) AS sum_grosssales FROM (SELECT D_PRODUCT.PRODUCT, D_PRODUCT.PRODUCT_ID, D_TIME.YEAR_MONTH, D_TIME.YYYYMM, D_ACCOUNT.ACCOUNT, D_ACCOUNT.UNIQUEIDACCOUNT -- Unique ID FROM D_PRODUCT CROSS JOIN D_TIME CROSS JOIN D_ACCOUNT WHERE D_TIME.YYYYMM >= TO_CHAR (ADD_MONTHS (SYSDATE, -48), 'YYYYMM') -- Récupération des 48 derniers mois AND D_TIME.YYYYMM < TO_CHAR (SYSDATE, 'YYYYMM') -- Récupération des données seulement jusqu'à aujourd'hui et pas jusque fin d'année 2015 AND D_ACCOUNT.COUNTRY = 'XX' -- Récupération Pays 'XX' seulement GROUP BY D_PRODUCT.PRODUCT, D_PRODUCT.PRODUCT_ID, D_TIME.YYYYMM, D_TIME.YEAR_MONTH, D_ACCOUNT.ACCOUNT, D_ACCOUNT.UNIQUEIDACCOUNT ) subquery LEFT JOIN ( SELECT SUM (NET_SALES) AS sub_sum_netsales, SUM (GROSS_SALES) AS sub_sum_gross, PRODUCT_ID, YYYYMM, UNIQUEIDACCOUNT FROM F_SALES WHERE YYYYMM >= TO_CHAR (ADD_MONTHS (SYSDATE, -48), 'YYYYMM') -- récupération des 48 derniers mois GROUP BY PRODUCT_ID, YYYYMM, UNIQUEIDACCOUNT) sub_sales ON sub_sales.PRODUCT_ID = subquery.PRODUCT_ID -- Jointure Product AND subquery.YYYYMM = sub_sales.YYYYMM - Jointure Time AND subquery.UNIQUEIDACCOUNT = sub_sales.UNIQUEIDACCOUNT - Jointure Account GROUP BY subquery.ACCOUNT, subquery.PRODUCT, subquery.YEAR_MONTH, TO_DATE (subquery.YEAR_MONTH, 'YYYY-MM');
Partager