优化具有大量连接的大型SQL查询

时间:2017-08-11 18:00:56

标签: sql sql-server

我正在寻找一种优化此Microsoft SQL查询的方法。

具体来说,我想得到以下问题的答案:

  1. 以何种方式可以并行化以下查询
  2. 什么可以在查询中优化,以便更快地运行? (我不希望任何人为我做这份工作,但是让我朝着正确的方向前进)。例如,如何更有效地完成许多连接?
  3. 通常有更好的方法来构建这么大的SQL查询吗?
  4. 感谢任何建议

        --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
    

2 个答案:

答案 0 :(得分:1)

神奇的单词是INDEX,只要连接条件可以使用索引就可以了。

还尝试从一开始就将表字段设置为正确的排序规则。在JOIN

期间不应该指出整理

此条件AND TEXP.EXPIRED = '9999-12-31 12:00:00 AM'如果你有无穷大的魔法值,最好使用NULL

遵循Guillaume建议使用查询分析器。但不要从整个查询开始。

  

你怎么吃大象?每次一小块。

从两个表开始,测试它,优化,添加另一个表并重复

答案 1 :(得分:0)

如果没有大量工作来分析您的查询并且没有关于数据库的更多信息,很难说。我们不知道来自不同表的此查询的负载。例如,如果你有一个包含100M记录的表,那么这将是一个完全不同的球赛,而每个表有少量记录的12个表,而13个表每个记录有7.5M记录。

但是,我看到一个可能的优化,我注意到你正在对结果进行不同的计算,具体取决于tm1.analysis_tenor或tm2.analysis_tenor是否为null。如果将查询分解为多个查询,其中每个查询分别执行其中一个案例,则无需对每个结果进行决策(案例表达式),并且在三个结果查询中,您将消除一个或多个连接

我说“可能”,因为它可能不会更快。就像@GuillaumeCR所说的那样,优化器做得非常好,你可能会发现这种变化会增加开销,而不是带走它。