2012-05-23 30 views
1

我已經在下面編寫了一個SQL腳本,並且遇到了運行速度的問題。直到「更新銷售數據」一節爲止。更新@Results表需要很長的時間。有什麼辦法可以加快速度嗎?如何加快SQL腳本的更新速度

USE [IV7] 
GO 
/*------------------------------------------------------------------------------------- ----------------- 
Declare all variables 
--------------------------------------------------------------------------------------- ---------------*/ 
DECLARE @StartDateTime DATETIME 
DECLARE @EndDateTime DATETIME 
DECLARE @l_Section  VARCHAR(100) 
DECLARE @Debug   CHAR(1) 

DECLARE @Worktable TABLE 
(
    PortfolioID  VARCHAR(20) 
, SettlementDate DATETIME 
, ContractDate DATETIME 
, BrokerCode  VARCHAR(100) 
, [Broker]  VARCHAR(100) 
, Currency  CHAR(3) 
, TransCode  CHAR(3) 
, TransactionType CHAR(3) 
, Nominal   DECIMAL(22,3) 
, ForwardRate  DECIMAL(22,8) 
, SpotRate  DECIMAl(22,8) 
, DealID   VARCHAR(20)  -- ThinkFolio ID 
, TranID   VARCHAR(20)  
, TranType  CHAR(3) 
, RKSTranID  VARCHAR(16)  -- This is the RKS transaction number. It is unique per transaction in RKS, but multi-leg transactions will have same value, allowing us to link them together (e.g. FX's, etc) 
, USDSPOTRate  FLOAT 
, BuyNominalUSD DECIMAL(22,3) 
) 

DECLARE @Results TABLE 
(
    PortfolioID  VARCHAR(20) 
, SettlementDate DATETIME 
, ContractDate DATETIME 
, BrokerCode  VARCHAR(100) 
, [Broker]  VARCHAR(100) 
, BuyCurrency  CHAR(3) 
, BuyNominal  DECIMAL(22,3) 
, SellCurrency CHAR(3) 
, SellNominal  DECIMAL(22,3) 
, MarketValue  DECIMAL(22,3) 
, ForwardRate  DECIMAL(22,8) 
, SpotRate  DECIMAL(22,8) 
, DealID   VARCHAR(20)  
, RKSTranID  VARCHAR(16)   -- Not used for final output 
, BuyNominalUSD DECIMAL(22,3)  
) 

DECLARE @FX TABLE 
( 
    RateDate  DATETIME 
, BaseCCY   CHAR(3) 
, RateCCY   CHAR(3) 
, MDInd   CHAR(1) 
, Rate   FLOAT 
, RateType  VARCHAR(10)  
) 
/*-------------------------------------------------------------------------------------------------------------------------------- 
Set default values 
--------------------------------------------------------------------------------------------------------------------------------*/ 
SET @l_Section = 'Setting Default Values' 
SET @StartDateTime = '2011-04-01 00:00:00.000' 
SET @EndDateTime = '2012-03-31 23:59:59.000' 
SET @Debug = 'Y' 

IF @Debug = 'Y' 
BEGIN 
    SELECT @l_Section 
    SELECT @StartDateTime AS StartDate, @EndDateTime AS EndDate 
END 
/*-------------------------------------------------------------------------------------------------------------------------------- 
Insert into FX 
--------------------------------------------------------------------------------------------------------------------------------*/ 
INSERT INTO @FX 
SELECT * FROM fn_Generic_FXRates ('2011-04-01','2012-03-31','D','SPOT','USD','999') 
/*-------------------------------------------------------------------------------------------------------------------------------- 
Insert values into @WorkTable 
--------------------------------------------------------------------------------------------------------------------------------*/ 
SET @l_Section = 'Insert values into @WorkTable' 

BEGIN 
INSERT INTO @WorkTable 
SELECT 
    t.acct_id         AS PortfolioID 
, t.cntrct_pay_tms       AS SettlementDate 
, t.trd_ex_eff_tms       AS ContractDate 
, t.trd_brkr_mnem        AS BrokerCode 
, t.trd_brkr_nme        AS Broker 
, t.local_curr_cde       AS Currency 
, t.trn_cl_cde        AS TransCode 
, t.trn_cde         AS TransactionType 
, t.quantity         AS Nominal 
, CASE 
     WHEN t.trn_cde IN ('FFB','FFS') THEN 
     t.fld4_rte ELSE NULL 
    END           AS ForwardRate 
, CASE 
     WHEN t.trn_cde IN ('FSB','FSS') THEN 
     t.fld4_rte ELSE NULL 
    END           AS Spot 
, t.exec_trd_id        AS DealID 
, t.actg_trn_id        AS TranID 
, t.trn_cde         AS TranType 
, t.deal_id         AS RKSTranID 
, fx.rate          AS USDSPOTRate 
, CASE 
     WHEN t.trn_cde IN ('FFB','FSB') THEN t.quantity * fx.rate 
     ELSE 0 
    END           AS BuyNominalUSD 

FROM tranevent_dg AS t 

INNER JOIN issue_dg AS i 
    ON i.instr_id = t.instr_id 
    AND i.iss_typ = 'FFX' 

INNER JOIN @FX AS fx 
      ON fx.RateCCY = t.local_curr_cde 
      AND fx.RateDate = t.trd_ex_eff_tms 

WHERE t.exec_trd_id IS NULL 
    AND t.inq_basis_num = 1 
    AND t.trd_ex_eff_tms BETWEEN @StartDateTime AND @EndDateTime 

ORDER BY t.deal_id 

END 

IF @Debug = 'Y' 
BEGIN 
    SELECT @l_Section 
    SELECT * FROM @WorkTable 
    ORDER BY RKSTranID 
END 
/*-------------------------------------------------------------------------------------------------------------------------------- 
Insert Buy values into @Results 
--------------------------------------------------------------------------------------------------------------------------------*/ 
SET @l_Section = 'Insert Buy values into @Results' 

BEGIN 
INSERT INTO @Results 
SELECT 
    w.PortfolioID  AS PortfolioID 
, CONVERT(VARCHAR(10),w.SettlementDate,112) AS SettlementDate 
, CONVERT(VARCHAR(10),w.ContractDate,112)  AS ContractDate 
, w.BrokerCode  AS BrokerCode 
, w.Broker   AS Broker 
, w.Currency   AS BuyCurrency 
, w.Nominal   AS BuyNominal 
, NULL    AS SellCurrency 
, NULL    AS SellNominal 
, NULL    AS MarketValue 
, w.ForwardRate  AS ForwardRate 
, w.SpotRate   AS SpotRate 
, w.DealID   AS DealID 
, w.RKSTranID   AS RKSTranID 
, w.BuyNominalUSD  AS BuyNominalUSD 

FROM @WorkTable AS w 
WHERE w.TranType IN ('FFB','FSB') 
ORDER BY w.RKSTranID 

END 

IF @Debug = 'Y' 
BEGIN 
    SELECT @l_Section 
    SELECT * FROM @Results 
    ORDER BY RKSTranID 
END 

/*-------------------------------------------------------------------------------------------------------------------------------- 
Update Buys with sales data 
--------------------------------------------------------------------------------------------------------------------------------*/ 
SET @l_Section = 'Update Buys with sales data' 

BEGIN 
UPDATE @Results 
SET 
    SellCurrency = wtSell.Currency 
, SellNominal = wtSell.Nominal 

FROM @Results AS r 

LEFT OUTER JOIN @WorkTable AS wtSell 
ON wtSell.PortfolioID = r.PortfolioID 
AND wtSell.RKSTranID = r.RKSTranID 
AND wtSell.TranType IN ('FFS','FSS') 

END 

IF @Debug = 'Y' 
BEGIN 
    SELECT @l_Section 
    SELECT * FROM @Results 
    ORDER BY RKSTranID 
END 
/*-------------------------------------------------------------------------------------------------------------------------------- 
Final Select 
--------------------------------------------------------------------------------------------------------------------------------*/ 
SET @l_Section = 'Final Output Select' 

SELECT 
PortfolioID  AS [Portfolio ID] 
, SettlementDate AS [Settlement Date] 
, ContractDate AS [Contract Date] 
, BrokerCode  AS [BrokerCode] 
, Broker   AS [Broker] 
, BuyCurrency  AS [Buy Ccy] 
, BuyNominal  AS [Buy Nominal] 
, BuyNominalUSD AS [Buy Nominal USD] 
, SellCurrency AS [Sell Ccy] 
, SellNominal  AS [Sell Nominal] 
, MarketValue  AS [Market Value] 
, ForwardRate  AS [Forward Rate] 
, SpotRate  AS [Spot Rate] 
, DealID   As [Deal ID] 

FROM @Results 

ORDER BY DealID 
+0

爲什麼使用左外連接? – Rawheiser

+0

另外:在這種情況下,表變量是不好的,原因有兩個:你不能在它們上面放置任何索引,其次,SQL Server查詢優化器將總是假設你的表變量只保存一行 - 而且這僅僅會導致它失敗基本上。你可以嘗試使它成爲'#Results'臨時表嗎? –

+0

我認爲添加整個代碼會讓人們更容易理解。 –

回答

0

只是爲了好玩 - 看看會發生什麼,如果你刪除訂單的每一次出現BY子句在INSERT,UPDATE,SELECT語句。

正如評論你應該真的試着放鬆表變量,並使用適當的(臨時)表添加適當的索引。

這個怎麼樣?我基本上把你所有的SQL合併成一個。顯然我無法測試它的準確性,但也許這會給你一些想法。您比我們更瞭解您的表格和數據,也許您可​​以根據需要刪除不必要的SQL。

SELECT 
    w.PortfolioID  AS PortfolioID 
    , CONVERT(VARCHAR(10),w.SettlementDate,112) AS SettlementDate 
    , CONVERT(VARCHAR(10),w.ContractDate,112)  AS ContractDate 
    , w.BrokerCode  AS BrokerCode 
    , w.Broker   AS Broker 
    , w.Currency   AS BuyCurrency 
    , w.Nominal   AS BuyNominal 
    , wtSell.Currency  AS SellCurrency -- wtSell 
    , wtSell.Nominal  AS SellNominal -- wtSell 
    , NULL    AS MarketValue 
    , w.ForwardRate  AS ForwardRate 
    , w.SpotRate   AS SpotRate 
    , w.DealID   AS DealID 
    , w.RKSTranID   AS RKSTranID 
    , w.BuyNominalUSD  AS BuyNominalUSD 
FROM 
(
    SELECT 
     t.acct_id         AS PortfolioID 
     , t.cntrct_pay_tms       AS SettlementDate 
     , t.trd_ex_eff_tms       AS ContractDate 
     , t.trd_brkr_mnem        AS BrokerCode 
     , t.trd_brkr_nme        AS Broker 
     , t.local_curr_cde       AS Currency 
     , t.trn_cl_cde        AS TransCode 
     , t.trn_cde         AS TransactionType 
     , t.quantity         AS Nominal 
     , CASE WHEN t.trn_cde IN ('FFB','FFS') THEN t.fld4_rte ELSE NULL END AS ForwardRate 
     , CASE WHEN t.trn_cde IN ('FSB','FSS') THEN t.fld4_rte ELSE NULL END AS Spot 
     , t.exec_trd_id        AS DealID 
     , t.actg_trn_id        AS TranID 
     , t.trn_cde         AS TranType 
     , t.deal_id         AS RKSTranID 
     , fx.rate          AS USDSPOTRate 
     , CASE WHEN t.trn_cde IN ('FFB','FSB') THEN t.quantity * fx.rate ELSE 0 END AS BuyNominalUSD 
    FROM 
     tranevent_dg AS t 
    INNER JOIN 
     issue_dg AS i ON i.instr_id = t.instr_id AND i.iss_typ = 'FFX' 
    INNER JOIN 
     @FX AS fx ON fx.RateCCY = t.local_curr_cde AND fx.RateDate = t.trd_ex_eff_tms 
    WHERE 
     t.exec_trd_id IS NULL 
    AND 
     t.inq_basis_num = 1 
    AND 
     t.trd_ex_eff_tms BETWEEN @StartDateTime AND @EndDateTime 
) AS w 
LEFT JOIN 
(
    SELECT 
     t.acct_id         AS PortfolioID 
     , t.cntrct_pay_tms       AS SettlementDate 
     , t.trd_ex_eff_tms       AS ContractDate 
     , t.trd_brkr_mnem        AS BrokerCode 
     , t.trd_brkr_nme        AS Broker 
     , t.local_curr_cde       AS Currency 
     , t.trn_cl_cde        AS TransCode 
     , t.trn_cde         AS TransactionType 
     , t.quantity         AS Nominal 
     , CASE WHEN t.trn_cde IN ('FFB','FFS') THEN t.fld4_rte ELSE NULL END AS ForwardRate 
     , CASE WHEN t.trn_cde IN ('FSB','FSS') THEN t.fld4_rte ELSE NULL END AS Spot 
     , t.exec_trd_id        AS DealID 
     , t.actg_trn_id        AS TranID 
     , t.trn_cde         AS TranType 
     , t.deal_id         AS RKSTranID 
     , fx.rate          AS USDSPOTRate 
     , CASE WHEN t.trn_cde IN ('FFB','FSB') THEN t.quantity * fx.rate ELSE 0 END AS BuyNominalUSD 
    FROM 
     tranevent_dg AS t 
    INNER JOIN 
     issue_dg AS i ON i.instr_id = t.instr_id AND i.iss_typ = 'FFX' 
    INNER JOIN 
     @FX AS fx ON fx.RateCCY = t.local_curr_cde AND fx.RateDate = t.trd_ex_eff_tms 
    WHERE 
     t.exec_trd_id IS NULL 
    AND 
     t.inq_basis_num = 1 
    AND 
     t.trd_ex_eff_tms BETWEEN @StartDateTime AND @EndDateTime 
) wtSell ON wtSell.PortfolioID = r.PortfolioID AND wtSell.RKSTranID = r.RKSTranID AND wtSell.TranType IN ('FFS','FSS') 
WHERE 
    w.TranType IN ('FFB','FSB') 
order by 
    w.DealID 

你可以通過簡單地比較你的SQL和這個組合語句的輸出來測試它的準確性。

+0

對不起,讓我這麼久回到這。我試着運行這個,並且運行時間與我上面發佈的腳本一樣長。 –