优化SQL Server查询以提高速度

时间:2015-10-16 07:45:25

标签: sql sql-server tsql query-optimization

如何优化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 
临时表中的

,但如果没有临时表,这甚至是最差的。我想选择最新的TransactionId(由MAX(TransactionStepId)制作,也可以选择左边的最后一个TransactionId

我的执行计划是:

enter image description here

enter image description here

2 个答案:

答案 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. 您的执行计划
  4. 这将有助于为您提供建议。

答案 1 :(得分:1)

有多个因素可以提高查询性能,其中一个可以完成,而不必了解有关索引,数据库架构,数据分布等的详细信息,这是查询中JOIN s的顺序。

我已经重构了你的查询,我认为你应该得到与以前相同的结果,但是执行时间有所改善:

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)