2015-10-16 128 views
0

如何優化我的SQL Server查詢?下面是我想優化優化SQL Server查詢速度

CREATE TABLE #Temp 
(
    TransactionId int PRIMARY KEY, 
    TransactionStepId int 
) 

INSERT INTO #Temp(TransactionId, TransactionStepId) 
    SELECT 
     TransactionId, MAX(TransactionStepId) TransactionStepId 
    FROM 
     [WarehouseMgmt].[FactPaymentTrans] FPT 
    JOIN 
     WarehouseMgmt.DimTimeZone DTZ on FPT.[TimeId] = DTZ.TimeUTCId 
    WHERE 
     FactType = 'SOURCE' 
     AND (DTZ.TimeId BETWEEN @DimStartDate AND @DimEndDate) 
    GROUP BY 
     TransactionId 

IF(UPPER(@ReportBy) = 'TRANSACTION') 
BEGIN 
SET @sql = ' 
    INSERT INTO #Results (  
    [PaymentTypeId], 
    [TransactionDate], 
    [PaymentMethodId], 
    [3DSecureId], 
    [ProductId], 
    [ProductTypeId], 
    [TransactionStatusId], 
    [Amount], 
    [Currency], 
    [PlayerId], 
    [PlayerSourceOrigId], 
    [Username], 
    [FirstName], 
    [LastName], 
    [BrandId], 
    [VIPLevelId], 
    [MarketingChannelId], 
    [MarketingSourceId], 
    [CommentId], 
    [CommentRefId], 
    [AdminName], 
    [OriginalTransactionId], 
    [TransactionId], 
    [RelatedTransactionId], 
    [ProviderTransactionOrigId] 
    ) 
    SELECT 
     DTST.[Id], 
     FPT.[StartTime], 
     FPT.[PaymentMethodId], 
     FPT.[3DSecureId], 
     FPT.[ProductId], 
     DPT.[Id], 
     FPT.[TransactionStatusId], 
     FPT.[Amount], 
     FPT.CurrencyId, 
     FPT.[PlayerId], 
     DPL.[SourceOrigId], 
     DPL.[Username], 
     DPL.[FirstName], 
     DPL.[LastName], 
     DPL.[BrandId], 
     DPL.[VIPLevelId], 
     DPL.[MarketingChannelId], 
     DPL.[MarketingSourceId], 
     FPT.[PaymentReasonTextId], 
     FPT_Ref.[PaymentReasonTextId], 
     FPT.CreatedByAdminId, 
     FPT.[OriginalTransactionId], 
     FPT.[TransactionId], 
     FPT_Ref.[OriginalTransactionId], 
     FPT.[ProviderTransactionOrigId] 
    FROM WarehouseMgmt.FactPaymentTrans AS FPT   
    JOIN #Temp T ON FPT.TransactionId = T.TransactionId AND FPT.TransactionStepId = T.TransactionStepId 
    JOIN WarehouseMgmt.DimTransactionStepType AS DTST ON FPT.[TransactionStepTypeId] = DTST.[Id] 
    JOIN WarehouseMgmt.DimPlayer AS DPL ON FPT.PlayerId = DPL.Id 
    JOIN WarehouseMgmt.DimProduct AS DP ON DP.Id = FPT.ProductId 
    JOIN WarehouseMgmt.DimProductType AS DPT ON DPT.Id = DP.ProductTypeId 
    --JOIN WarehouseMgmt.DimTimeZone DTZ on FPT.[TimeId] = DTZ.TimeUTCId 
    JOIN [WarehouseMgmt].[DimLoyaltyProgramLevel] DLPL ON DLPL.[Id]=DPL.VipLevelId  
    LEFT JOIN 
    (
       SELECT FPT_Ref_1.TransactionId,FPT_Ref_1.FactType,FPT_Ref_1.OriginalTransactionId,FPT_Ref_1.[PaymentReasonTextId] 
       FROM WarehouseMgmt.FactPaymentTrans AS FPT_Ref_1       
       JOIN #Temp T ON T.TransactionId = FPT_Ref_1.OriginalTransactionId AND T.TransactionStepId = FPT_Ref_1.TransactionStepId 
    ) AS FPT_Ref ON FPT_Ref.OriginalTransactionId = FPT.TransactionId AND FPT_Ref.FactType = ''SOURCE'' 
    WHERE (FPT.FactType = ''SOURCE'') ' + @sqlFilters 

我試圖把這個

  SELECT TransactionId,MAX(TransactionStepId) TransactionStepId 
      FROM [WarehouseMgmt].[FactPaymentTrans] 
      WHERE FactType = ''SOURCE'' 
      GROUP BY TransactionId 

在臨時表的代碼,但是這是最糟糕的,甚至如果沒有臨時表。我想選擇由MAX(TransactionStepId取得最新TRANSACTIONID(那),並在左側選擇最後TRANSACTIONID JOIN

我的執行計劃是:

enter image description here

enter image description here

+0

你能共享一個執行計劃?有關表格索引的詳細信息?此外,查詢結尾還有一個小撇號。這有沒有什麼用處(*可能是一些缺少的代碼?*)還是這是一個錯誤? –

+0

你可以嘗試我的查詢,看看執行時間是否有任何改進? –

回答

1

你有沒有考慮使用ROW_NUMBER而不是加入表格兩次?請嘗試此操作:

;WITH FactPaymentTrans_Last 
AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY TransactionID ORDER BY TransactionStepID DESC) AS RN 
    FROM WarehouseMgmt.FactPaymentTrans 
    ) 
SELECT DTST.[Id] 
    , FPT.[StartTime] 
    , FPT.[PaymentMethodId] 
    , FPT.[3DSecureId] 
    , FPT.[ProductId] 
    , DPT.[Id] 
    , FPT.[TransactionStatusId] 
    , FPT.[Amount] 
    , FPT.CurrencyId 
    , FPT.[PlayerId] 
    , DPL.[SourceOrigId] 
    , DPL.[Username] 
    , DPL.[FirstName] 
    , DPL.[LastName] 
    , DPL.[BrandId] 
    , DPL.[VIPLevelId] 
    , DPL.[MarketingChannelId] 
    , DPL.[MarketingSourceId] 
    , FPT.[PaymentReasonTextId] 
    , FPT_Ref.[PaymentReasonTextId] 
    , FPT.CreatedByAdminId 
    , FPT.[OriginalTransactionId] 
    , FPT.[TransactionId] 
    , FPT_Ref.[OriginalTransactionId] 
    , FPT.[ProviderTransactionOrigId] 
FROM FactPaymentTrans_Last AS FPT 
INNER JOIN WarehouseMgmt.DimTransactionStepType AS DTST 
    ON FPT.[TransactionStepTypeId] = DTST.[Id] 
INNER JOIN WarehouseMgmt.DimPlayer AS DPL 
    ON FPT.PlayerId = DPL.Id 
INNER JOIN WarehouseMgmt.DimProduct AS DP 
    ON DP.Id = FPT.ProductId 
WHERE FPT.RN = 1; 

這只是一個片段,讓你知道如何使用它來得到最新的TransactionIds根據其TransactionStepId

如果這還不夠 - 請發佈這些:

  1. 你的表結構
  2. 他們
  3. 你執行計劃

指數這將有助於給你的建議。

+0

我在我的問題中添加了執行計劃 – user2171512

1

有多種因素可以提高查詢性能,其中一項可以完成,而不必知道有關索引,數據庫模式,數據分佈等的詳細信息,這是查詢中JOIN的順序。

我已經重構你的查詢,我認爲你應該像以前一樣得到同樣的結果,但有一個改進的執行時間:

SELECT DTST.[Id] 
    ,FPT.[StartTime] 
    ,FPT.[PaymentMethodId] 
    ,FPT.[3DSecureId] 
    ,FPT.[ProductId] 
    ,DPT.[Id] 
    ,FPT.[TransactionStatusId] 
    ,FPT.[Amount] 
    ,FPT.CurrencyId 
    ,FPT.[PlayerId] 
    ,DPL.[SourceOrigId] 
    ,DPL.[Username] 
    ,DPL.[FirstName] 
    ,DPL.[LastName] 
    ,DPL.[BrandId] 
    ,DPL.[VIPLevelId] 
    ,DPL.[MarketingChannelId] 
    ,DPL.[MarketingSourceId] 
    ,FPT.[PaymentReasonTextId] 
    ,FPT_Ref.[PaymentReasonTextId] 
    ,FPT.CreatedByAdminId 
    ,FPT.[OriginalTransactionId] 
    ,FPT.[TransactionId] 
    ,FPT_Ref.[OriginalTransactionId] 
    ,FPT.[ProviderTransactionOrigId] 
FROM WarehouseMgmt.FactPaymentTrans AS FPT 
INNER JOIN WarehouseMgmt.DimPlayer AS DPL 
    ON FPT.PlayerId = DPL.Id 
INNER JOIN WarehouseMgmt.DimProduct AS DP 
    ON DP.Id = FPT.ProductId 
INNER JOIN WarehouseMgmt.DimProductType AS DPT 
    ON DPT.Id = DP.ProductTypeId 
INNER JOIN WarehouseMgmt.DimTransactionStepType AS DTST 
    ON FPT.[TransactionStepTypeId] = DTST.[Id]  
WHERE (FPT.FactType = '' SOURCE '') 
    AND EXISTS (SELECT 1 
       FROM [WarehouseMgmt].[FactPaymentTrans] 
       WHERE FactType = '' SOURCE '' 
        AND FPT.TransactionId = TransactionId 
        AND FPT.TransactionStepId = TransactionStepId) 
    AND EXISTS (SELECT 1 
       FROM [WarehouseMgmt].[DimLoyaltyProgramLevel] DLPL 
       WHERE DLPL.[Id] = DPL.VipLevelId) 
    AND EXISTS (SELECT 1 
       FROM WarehouseMgmt.DimTimeZone DTZ 
       WHERE FPT.[TimeId] = DTZ.TimeUTCId 
        AND DTZ.TimeId BETWEEN @DimStartDate AND @DimEndDate) 
+0

首先你沒有FPT_Ref表,第二個不能過濾時間,然後在該表上進行連接,它返回錯誤。請參閱我的代碼並進行相同的更改 – user2171512

+0

@ user2171512這個想法是它不應該是相同的(有些查詢是多餘的)。我已經對查詢進行了更正,以便篩選器可以使用「進入時間」。請嘗試新的查詢。 –

+0

我仍然有FPT_Ref [PaymentReasonTextId]和FPT_Ref [OriginalTransactionId]錯誤。那是我的參考表格(加入表格)。我該如何解決這個問題和以前一樣? – user2171512