2016-12-14 111 views
0

我正在尋找一些提示/技巧來提高插入到表中的多個SELECT語句的存儲過程的性能。我加入的所有對象都已編入索引。提高sql查詢的性能

我相信這個存儲過程需要近一個小時運行的原因是因爲有多個SELECT語句中使用以下兩種觀點:rvw_FinancialLineItemValues和rvw_FinancialLineItems

而且,每個SELECT語句使用特定的硬編碼值的賬戶號碼, 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 
+1

您是否查看過查詢執行計劃和/或估計是否存在導致大部分執行時間的特定節點? – Anand

回答

1

首先,您使用的是UDF fn_split()?如果您沒有使用表內值爲的內聯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 
1

見我看向第一以下。什麼是與您的存儲過程相關的等待類型?你是否看到很多磁盤io時間?事情是在記憶中完成的嗎?也許有網絡延遲拉動這麼多的信息。

接下來,該程序的計劃是什麼樣子,它顯示所有工作正在完成的地方?

您提到的觀點絕對可能是一個問題。你可能可能有預處理表,所以你不必做很多連接。特別是您看到CPU花費最多的連接。

1

相關子查詢通常很慢,在嘗試性能時不應使用。使用fn_split創建一個臨時表索引,如果需要的話,然後加入它來獲得你需要的值。您可能需要多次加入不同的值,但實際上並不知道我難以想象的數據。

這對使用OR的性能也不好。相反,在派生表中使用UNION ALL。

既然你對視rvw_FinancialLineItems所有這些條件,是的,它可能會工作到那些拉出來到一個臨時表,然後索引臨時表。

YOu也可能會看到使用視圖是否是一個好主意。通常情況下,許多表都會加入許多表,表示您沒有從中獲取數據,因此性能低於僅查詢實際需要的表。如果您的組織愚蠢到可以提出觀點並發表意見,那麼情況尤其如此。