我正在寻找一种优化此Microsoft 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
答案 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所说的那样,优化器做得非常好,你可能会发现这种变化会增加开销,而不是带走它。