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

具有大量连接的大型SQL查询优化,sql,sql-server,Sql,Sql Server,我正在寻找一种优化此Microsoft SQL查询的方法 具体而言,我想回答以下问题: 我可以用什么方式并行下面的查询 查询中可以优化哪些内容以使其运行更快?我不指望有人替我做这项工作,而是希望把我带向正确的方向。例如,如何更有效地完成多个连接? 通常有更好的方法来构造这样一个大型SQL查询吗? 如有任何建议,我们将不胜感激 --IF (OBJECT_ID('SATURN_REPORTING.RISKDATA')) IS NOT NULL -- DROP TABLE SA

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

具体而言,我想回答以下问题:

我可以用什么方式并行下面的查询 查询中可以优化哪些内容以使其运行更快?我不指望有人替我做这项工作,而是希望把我带向正确的方向。例如,如何更有效地完成多个连接? 通常有更好的方法来构造这样一个大型SQL查询吗? 如有任何建议,我们将不胜感激

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

我们需要查看您的数据库结构,以便您了解情况。SQL非常擅长并行化它所能做的事情,所以我不担心尝试手动执行它:您更可能妨碍优化器的工作,而不是帮助它

,尽管已经很老了,但仍然有一些关于如何使用查询计划可视化工具帮助理解查询瓶颈的好技巧。在您确切了解SQL的哪个部分有问题之前,不要开始优化

给我们查询计划可视化工具的结果,以帮助我们帮助您。

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

另外,请尝试从一开始就将表字段设置为正确的排序规则。在联接过程中不需要指示排序规则

此条件和TEXP.EXPIRED='9999-12-31 12:00:00 AM',如果您有无穷大的神奇值,最好使用NULL

另外,按照纪尧姆的建议使用查询分析器。但不要从整个查询开始

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


从两个表开始,对其进行测试、优化、添加另一个表并重复

如果不在分析查询方面投入大量工作,并且没有关于数据库的更多信息,很难说。对于这个查询从不同的表中加载的内容,我们没有任何线索。例如,如果你有一张100米记录的桌位,12张桌位各有少量记录,而13张桌位各有7.5米记录,这将是一场完全不同的球赛。 然而,我看到的一个可能的优化是,我注意到您正在对结果进行不同的计算,这取决于tm1.analysis\u tenor还是tm2.analysis\u tenor为空。如果将查询分解为多个查询,其中每个查询分别执行其中一个案例,则无需在每个结果上使用决策案例表达式,而在三个结果查询上,则无需使用一个或多个联接。
我说可能是因为它最终可能不会更快。正如@GuillaumeCR所说,优化器做得非常好,您可能会发现,这一更改增加的开销比它所带来的开销还要多。

您想了解数据库结构的具体信息吗?索引和排序规则。在执行过程中,不需要指示排序规则join@nickpick我还不知道,我需要查询计划可视化来获得更好的想法。临时表没有什么丢脸的地方。当我看到这样的大型查询时,我倾向于将核心数据放入带有适当初始过滤器的临时表中,然后从中构建。您可能会对性能的提高感到惊讶。例如,使用临时表对一个耗时34秒以上的核心查询进行了重新设置,最终运行时间不到2秒。@johncapelletti及其生成的查询通常更易于理解、测试和维护。