Je cherche un moyen d'optimiser cette requête Microsoft SQL.

Plus précisément, j'aimerais obtenir une réponse aux questions suivantes:

  1. De quelle manière puis-je paralléliser la requête ci-dessous
  2. Que peut-on optimiser dans la requête pour qu'elle s'exécute plus rapidement? (Je ne m'attends pas à ce que quelqu'un fasse le travail à ma place, mais me mette dans la bonne direction). Par exemple, comment les nombreuses jointures peuvent-elles être effectuées plus efficacement?
  3. Existe-t-il généralement un meilleur moyen de structurer une requête SQL aussi volumineuse?

Toutes les suggestions sont appréciées

    --IF (OBJECT_ID('SATURN_REPORTING.RISKDATA')) IS NOT NULL
    --     DROP TABLE SATURN_REPORTING.RISKDATA    
    --GO

    DECLARE @COB_DATE VARCHAR(10);
    SET @COB_DATE = '2017-06-30';

    SELECT  
            R.COB_DATE,

            FD.ASSET_CLASS,
            FD.SOURCE_SYSTEM,         
            CASE 
                         WHEN TM1.ANALYSIS_TENOR IS NOT NULL AND TM2.ANALYSIS_TENOR IS NOT NULL THEN (TM1.MULTIPLIER * TM2.MULTIPLIER * R.VALUE)
                            ,,,,
                         WHEN TM1.ANALYSIS_TENOR IS NULL AND TM2.ANALYSIS_TENOR IS NOT NULL THEN (TM2.MULTIPLIER * R.VALUE)
                  ELSE R.VALUE END AS CCY_VALUE,
            CASE 
                         WHEN TM1.ANALYSIS_TENOR IS NOT NULL AND TM2.ANALYSIS_TENOR IS NOT NULL THEN (TM1.MULTIPLIER * TM2.MULTIPLIER * R.VALUE * X.GBP_RATE)
                          ...
                         WHEN TM1.ANALYSIS_TENOR IS NULL AND TM2.ANALYSIS_TENOR IS NOT NULL THEN (TM2.MULTIPLIER * R.VALUE * X.GBP_RATE)
                  ELSE (R.VALUE * X.GBP_RATE) END AS GBP_VALUE,
            R.UNIT AS R_UNIT,
            RFC1.RISK_FACTOR_TYPE RFC_RISK_FACTOR_TYPE, 
          ...
            P.TRADE_VERSION AS P_TRADE_VERSION, 
            TR.COUNTER_PARTY_NAME AS TR_COUNTER_PARTY_NAME,
            TR.LOCATION AS TR_LOCATION,
            TR.STRIKE AS TR_STRIKE,
            P.CUST_ID AS P_CUST_ID, 
            P.SENIORITY AS P_SENIORITY,
            P.ISSUER_OPERATION_CTRY_NAME AS P_ISSUER_OPERATION_CTRY_NAME, 
        ...
            P.MATURITY_DATE AS P_MATURITY_DATE, 
            P.NDF AS P_NDF, 
            P.OFFSHORE AS P_OFFSHORE, 
            P.COLLATERAL_COUPON AS P_COLLATERAL_COUPON, 
            P.IN_DEFAULT AS P_IN_DEFAULT,
            ISS.ISSUER_NAME AS ISS_ISSUER_NAME, 
       ...
    ...
            INS.TRANCHE_NAME AS INS_TRANCHE_NAME                       

    INTO    SATURN_REPORTING.RISKDATA1

    FROM    SATURN_REPORTING.RISK R
    INNER JOIN SATURN_REPORTING.RISK_TYPE RT 
        ON RT.RISK_TYPE = R.RISK_TYPE
    INNER JOIN SATURN_REPORTING.FD ON FD.FEED_CODE = R.FEED_CODE
    INNER JOIN SATURN_REPORTING.DIM_TRANSFORM_TYPE TT 
        ON TT.TRANSFORM_KEY = R.TRANSFORM_TYPE                    
    INNER JOIN SATURN_REPORTING.X_RATE X 
        ON X.CURRENCY = R.UNIT
        AND X.COB_DATE = R.COB_DATE
    LEFT JOIN SATURN_REPORTING.RISK_FACTOR_CURVE RFC1 
        ON RFC1.COB_DATE = R.COB_DATE
        AND RFC1.ID = R.DIM_1_CURVE_ID
    LEFT JOIN SATURN_REPORTING.RISK_FACTOR_POINT RFP1
           ON RFP1.ID = R.DIM_1_POINT_ID
           AND RFP1.COB_DATE = @COB_DATE
    LEFT JOIN SATURN_REPORTING.TENOR TMAT
            ON RFP1.COB_DATE = TMAT.COB_DATE
            AND RFP1.MATURITY_TENOR = TMAT.TENOR
            AND TMAT.EXPIRED = '9999-12-31 12:00:00 AM'    
    LEFT JOIN SBA.TENORMAPPING TM1
           ON TM1.SIMPLE_TENOR = TMAT.SIMPLE_TENOR
    LEFT JOIN SATURN_REPORTING.TENOR TEXP
            ON RFP1.COB_DATE = TEXP.COB_DATE
            AND RFP1.EXPIRY_TENOR = TEXP.TENOR
            AND TEXP.EXPIRED = '9999-12-31 12:00:00 AM'    
    LEFT JOIN SBA.TENORMAPPING TM2
           ON TM2.SIMPLE_TENOR = TEXP.SIMPLE_TENOR
    LEFT JOIN SATURN_REPORTING.POSITION P 
        ON P.ID = R.POSITION_ID
    LEFT JOIN SATURN_REPORTING.TRADE TR
      ON TR.TRADE_ID COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS = P.TRADE_ID COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS
      AND TR.TRADE_VERSION = P.TRADE_VERSION
      AND TR.TRADE_ID_TYPE COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS = P.TRADE_ID COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS
    LEFT JOIN SATURN_REPORTING.ISSUER ISS 
        ON ISS.ISSUER_ID = P.ISSUER_ID
        AND ISS.ISSUER_ID_TYPE COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS = P.ISSUER_ID_TYPE COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS
        AND ISS.ISSUER_VERSION = P.ISSUER_VERSION
    LEFT JOIN SATURN_REPORTING.INSTRUMENT INS 
        ON INS.INSTRUMENT_ID COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS = P.INSTRUMENT_ID COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS
        AND INS.INSTRUMENT_ID_TYPE COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS = P.INSTRUMENT_ID_TYPE COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS
        AND INS.INSTRUMENT_VERSION = P.INSTRUMENT_VERSION
    LEFT JOIN SATURN_REPORTING.ASSET_HIERARCHY_MAPPING AHM
        ON AHM.ASSET COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS = RFC1.INSTRUMENT_LABEL COLLATE SQL_LATIN1_GENERAL_CP1_CS_AS
        AND R.COB_DATE BETWEEN AHM.FROM_COB_DATE AND AHM.TO_COB_DATE
    AND    AHM.EXPIRED = 'Dec 31 9999 12:00AM'
    WHERE   R.COB_DATE = @COB_DATE
    AND     R.EXPIRED = '9999-12-31'
    AND     TT.TRANSFORM = 'FINAL'
    AND     X.EXPIRED = '9999-12-31 00:00:00'
    AND R.RISK_TYPE IN (
           'CONUDL',
      ...
           'IRIN',
           'IRINT',
      ...
           'SARO',
       ...
    )
    GO        

    /****** Object:  Index [RISKDATA_IDX_001]    Script Date: 17/02/2015 14:29:18 ******/
    CREATE NONCLUSTERED INDEX [RISKDATA_IDX_001] ON [SATURN_REPORTING].[RISKDATA1]
    (
           [RISK_BOOK] ASC,
           [FEED_CODE] ASC,
           [RISK_TYPE] ASC,
           [MAT_BUCKET] ASC,
           [EXP_BUCKET] ASC,
           [R_UNIT] ASC,
           [RFC_SOURCE_PRICING_CURVE] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    GO
0
Nickpick 11 août 2017 à 21:00

2 réponses

Meilleure réponse

Le mot magique est INDEX, tant que les conditions de jointure peuvent utiliser un index, vous serez OK.

Essayez également de configurer les champs de votre table avec le bon classement depuis le début. Il ne devrait pas être nécessaire d'indiquer le classement pendant le JOIN

Cette condition AND TEXP.EXPIRED = '9999-12-31 12:00:00 AM' si vous avez une valeur magique pour l'infini est préférable d'utiliser NULL

En suivant également la suggestion de Guillaume, utilisez l'Analyseur de requêtes. Mais ne commencez pas par toute la requête.

Comment mangez-vous un éléphant? un petit morceau à chaque fois.

Commencez avec deux tableaux, testez-les, optimisez, ajoutez un autre tableau et répétez

1
Juan Carlos Oropeza 14 août 2017 à 14:02

C'est difficile à dire sans consacrer beaucoup de travail à l'analyse de votre requête et sans avoir plus d'informations sur votre base de données. Nous n'avons aucune idée des charges sur cette requête à partir des différentes tables. Par exemple, ce serait un jeu de balle entièrement différent si vous avez une table avec 100 millions d'enregistrements et 12 tables avec une poignée d'enregistrements chacune, contre 13 tables avec 7,5 millions d'enregistrements chacune.

Cependant, une optimisation possible que je vois serait que je remarque que vous faites des calculs différents pour vos résultats selon que tm1.analysis_tenor ou tm2.analysis_tenor sont nuls. Si vous divisez la requête en plusieurs requêtes où chacune fait l'un de ces cas séparément, vous éliminerez le besoin de prise de décision (expression de cas) sur chaque résultat, et sur trois des requêtes résultantes, vous élimineriez une ou plusieurs jointures .

Je dis «possible» parce que cela ne sera peut-être pas plus rapide. Comme @GuillaumeCR l'a dit, l'optimiseur fait un très bon travail et vous constaterez peut-être que ce changement ajoute plus de frais généraux qu'il n'en enlève.

0
11 août 2017 à 18:44