簡體   English   中英

提高SQL查詢的性能

[英]Improve performance of a sql query

我正在尋找一些技巧/技巧,以通過將多個SELECT語句插入表中來提高存儲過程的性能。 我加入的所有對象均已建立索引。

我相信運行此存儲過程將花費一個小時左右的原因是因為有多個SELECT語句使用以下兩個視圖:rvw_FinancialLineItemValues和rvw_FinancialLineItems

另外,每個SELECT語句都使用特定的硬編碼值來表示AccountNumber,LineItemTypeID和來自上述兩個視圖的其他幾個字段值。

如果我創建一個臨時表,該表一次獲取這些SELECT語句所需的所有數據,然后在聯接中使用該臨時表,是否會提高性能?

還有其他方法可以改善性能和可管理性嗎?

        SELECT
         @scenarioid,
         @portfolioid,
         pa.Id,
         pa.ExternalID,       
         (select value from fn_split(i.AccountNumber,'.') where id = 1),
         ac.[Description],
         cl.Name,
         NullIf((select value from fn_split(i.AccountNumber,'.') where id = 2),''),
         NullIf((select value from fn_split(i.AccountNumber,'.') where id = 3),''),
         ty.Name,
         v.[Date],
         cast(SUM(v.Amount) as decimal(13,2)),
         GETDATE()

    FROM rvw_FinancialLineItems i
    INNER JOIN rvw_Scenarios sc
        ON i.ScenarioId = sc.Id
        AND sc.Id = @scenarioid
        AND sc.PortfolioId = @portfolioid
    INNER JOIN #pa AS pa
        ON i.PropertyAssetID = pa.Id
    INNER JOIN rvw_FinancialLineItemValues v
        ON i.ScenarioId = v.ScenarioId
        AND i.PropertyAssetID = v.PropertyAssetID
        AND i.Id = v.FinancialLineItemId
        AND ((i.BusinessEntityTypeId = 11
        AND i.LineItemTypeId = 3002)
        OR (i.LineItemTypeId IN (2005, 2010, 2003, 2125, 2209, 5012, 6001)
        AND i.ModeledEntityKey = 1))
        AND i.AccountNumber not in ('401ZZ','403ZZ')
  AND i.AccountNumber not in ('401XX')
        AND i.AccountNumber not in ('40310','41110','42010','41510','40190','40110')  -- exclude lease-level revenues selected below
        AND v.[Date] BETWEEN @fromdate AND 
          CASE
            WHEN pa.AnalysisEnd < @todate THEN pa.AnalysisEnd
            ELSE @todate
          END
        AND v.ResultSet IN (0, 4)
    INNER JOIN rvw_Portfolios po
        ON po.Id = @portfolioid
    INNER JOIN Accounts ac
        ON po.ChartOfAccountId = ac.ChartOfAccountId
        AND i.AccountNumber = ac.AccountNumber
        AND ac.HasSubAccounts = 0
    INNER JOIN fn_LookupClassTypes() cl
        ON ac.ClassTypeId = cl.Id
    INNER JOIN LineItemTypes ty
        ON ac.LineItemTypeId = ty.Id
    LEFT JOIN OtherRevenues r
        ON i.PropertyAssetID = r.PropertyAssetID
        AND i.AccountNumber = r.AccountID
        AND v.[Date] BETWEEN r.[Begin] AND r.[End]
    WHERE (r.IsMemo IS NULL
    OR r.IsMemo = 0)
    GROUP BY    pa.AnalysisBegin
                ,pa.Id
                ,pa.ExternalID
                ,i.AccountNumber
                ,ac.[Description]
                ,cl.Name
                ,ty.Name
                ,v.[Date]
    HAVING SUM(v.amount) <> 0

您應該使用SET SHOWPLAN ALL ON或Management Studio Save Execution Plan來運行查詢,並尋找效率低下的問題。

有一些在線資源可幫助您分析結果,例如: http : //www.sqlservercentral.com/articles/books/65831/

另請參閱如何獲取查詢執行計划?

我將首先關注以下內容。 與您的存儲過程有關的等待類型是什么? 您看到很多磁盤io時間了嗎? 事情正在記憶中完成嗎? 也許網絡延遲會拉動這么多信息。

接下來,該程序的計划是什么樣的,它在哪里顯示所有工作已完成?

正如您提到的,這些觀點肯定是一個問題。 您可能已經對表進行了預處理,因此不必進行太多的聯接。 特別是您在其中看到最多CPU使用量的聯接。

關聯的子查詢通常很慢,在嘗試提高性能時切勿使用。 使用fn_split創建一個臨時表(如果需要)對其進行索引,然后加入該表以獲取所需的值。 您可能需要多次連接以獲得不同的值,而實際上不知道我很難可視化的數據。

使用OR也不利於性能。 而是在派生表中使用UNION ALL。

由於您在視圖rvw_FinancialLineItems上具有所有這些條件,因此可以將這些條件拉出到臨時表,然后為臨時表建立索引可能會起作用。

您可能還會看到使用視圖是否是個好主意。 視圖通常會連接到許多您沒有從中獲取數據的表,因此它們的性能要比僅查詢實際需要的表低。 如果您的組織足夠愚蠢,無法創建調用視圖的視圖,則尤其如此。

首先,您使用的是哪個fn_split() UDF? 如果您沒有使用表值內聯UDF,那么這非常慢。

其次,UDF fn_LookupClassTypes()是一個內聯表,其值為UDF嗎? 如果不是,請將其轉換為內聯表值UDF。

最后,您的SQL查詢有一些冗余。 試試這個,看看它能做什么。

SELECT @scenarioid, @portfolioid, pa.Id, pa.ExternalID,       
      (select value from fn_split(i.AccountNumber,'.') 
       where id = 1),  ac.[Description], cl.Name,
     NullIf((select value from fn_split(i.AccountNumber,'.') 
             where id = 2),''),
     NullIf((select value from fn_split(i.AccountNumber,'.') 
             where id = 3),''), ty.Name, v.[Date],
     cast(SUM(v.Amount) as decimal(13,2)), GETDATE()

FROM rvw_FinancialLineItems i
   JOIN rvw_Scenarios sc ON sc.Id = i.ScenarioId 
   JOIN #pa AS pa ON pa.Id = i.PropertyAssetID  
   JOIN rvw_FinancialLineItemValues v
      ON v.ScenarioId = i.ScenarioId
        AND v.PropertyAssetID = i.PropertyAssetID
        AND v.FinancialLineItemId = i.Id  
   JOIN rvw_Portfolios po ON po.Id = sc.portfolioid
   JOIN Accounts ac
      ON ac.ChartOfAccountId = po.ChartOfAccountId
         AND ac.AccountNumber = i.AccountNumber
   JOIN fn_LookupClassTypes() cl On cl.Id = ac.ClassTypeId 
   JOIN LineItemTypes ty On ty.Id = ac.LineItemTypeId
   Left JOIN OtherRevenues r
      ON r.PropertyAssetID = i.PropertyAssetID
        AND r.AccountID = i.AccountNumber  
        AND v.[Date] BETWEEN r.[Begin] AND r.[End]

WHERE i.ScenarioId = @scenarioid
   and ac.HasSubAccounts = 0
   and sc.PortfolioId = @portfolioid
   and IsNull(r.IsMemo, 0) = 0)
   and v.ResultSet In (0, 4)
   and i.AccountNumber not in
          ('401XX', '401ZZ','403ZZ','40310','41110',
           '42010','41510','40190','40110')
   and v.[Date] BETWEEN @fromdate AND 
            CASE WHEN pa.AnalysisEnd < @todate 
                 THEN pa.AnalysisEnd ELSE @todate END
   and ((i.LineItemTypeId = 3002 and i.BusinessEntityTypeId = 11) OR 
           (i.ModeledEntityKey = 1 and i.LineItemTypeId IN 
               (2005, 2010, 2003, 2125, 2209, 5012, 6001)))

GROUP BY pa.AnalysisBegin,pa.Id, pa.ExternalID, i.AccountNumber, 
      ac.[Description],cl.Name,ty.Name,v.[Date]
HAVING SUM(v.amount) <> 0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM