0

我正在改進使用FOR XML PATH('')函數使用20列的視圖性能。該視圖還調用其他字段使用非聚集視圖CTE,子查詢和CAST函數,但我現在不關心它們。FOR XML PATH性能改進挑戰

該視圖是一個非聚集視圖,每5分鐘由作業選擇該視圖以將新數據顯示給客戶端應用程序。因此底層源表格正在更新並每隔5分鐘插入一個井。

我已經在適當的地方創建了羣集和非羣集索引。在創建相應索引之前對源表上的各個視圖組件進行了測試,之後選擇了最佳路由。所以,我在索引方面做得很好。在所有指標上,填充因子值幾乎爲100。

我的假設是,查詢速度放緩了很多,因爲我使用的針對20列XML PATH(「」)......

CREATE VIEW MyView 
AS 
col1, 
Col2, 
(SELECT CAST(Mytbl.[EmpId] AS NVARCHAR(50)) + '|' FROM MyDB.dbo.Mytbl_Optimized AS t1 (NOLOCK) 
      LEFT OUTER JOIN AnotherDB.dbo.Another-tbl AS t2 WITH (NOLOCK) 
      ON t1.EmpId = t2.EmpId 
WHERE AnotherDB.dbo.Table3.MyId = t1.MyId 
FOR XML PATH('')) AS MyConcatenatedID 
FROM AnotherDB.dbo.Table3 

我試圖用它確定一個CASE語句如果每個列都帶有FOR XML PATH('')任何要逐行連接的基礎,然後僅當is有2個或更多個值連接到一個字符串時才使用FOR XML PATH('')。但正如我所期望的性能是可怕的......

,CASE 
     WHEN 
      (SELECT 
       LEN(EmpId) - LEN(REPLACE(EmpId, '|', '')) AS [CountOfConcatinated_EmpId] 
      FROM ISSearch..SearchBid WITH (NOLOCK) 
      ) > 1 -- this determis if values are concatenated or not. 
     THEN 
      (SELECT CAST(Mytbl.[EmpId] AS NVARCHAR(50)) + '|' FROM MyDB.dbo.Mytbl_Optimized AS t1 (NOLOCK) 
       LEFT OUTER JOIN AnotherDB.dbo.Another-tbl AS t2 WITH (NOLOCK) 
       ON t1.EmpId = t2.EmpId 
       WHERE AnotherDB.dbo.Table3.MyId = t1.MyId 
     FOR XML PATH('')) 

     ELSE 
      (SELECT CAST(Mytbl.[EmpId] AS NVARCHAR(50)) + '|' FROM MyDB.dbo.Mytbl_Optimized AS t1 (NOLOCK) 
       LEFT OUTER JOIN AnotherDB.dbo.Another-tbl AS t2 WITH (NOLOCK) 
       ON t1.EmpId = t2.EmpId 
       WHERE AnotherDB.dbo.Table3.MyId = t1.MyId) 
     END AS EmpId 
FROM AnotherDB.dbo.MyView; 

現在我考慮已經由FOR XML PATH(「」)的所有20列,在視圖單獨的列的函數字符串連接在一起的緩存選項,但需要不斷更新(每5分鐘)。

任何想法或替代解決方案?

+0

我假設'AnotherDB.dbo.Another-tbl作爲t2'是一個虛擬名稱,但那些需要離開連接(或在那裏)?至少在提供的查詢中,他們似乎沒有做任何事情。我想知道一些其他的事情:1)有多少行被連接到'MyConcatednatedId'的每個值中2)在'Table3'中有多少行3)它現在的表現有多慢4)你有多快需要它? – Xedni

+0

使用[粘貼計劃@ brentozar.com](https://www.brentozar.com/pastetheplan/)分享您的執行計劃以下是說明:[如何使用粘貼計劃](https://www.brentozar的.com/pastetheplan /指令/)。 – SqlZim

回答

0

模糊的問題會得到模糊的答案,但這裏有。

我同意這似乎很可能所有的FOR XML串聯可能是貢獻(並且肯定沒有看到一個執行計劃或您的完整數據庫模式,幾乎我唯一要去)。這裏有很多未知數可能會改變建議。如果你可以包含你的查詢計劃和IO統計數據,這將有所幫助。

我也不要求具體知道爲什麼,或者如果你需要使用一個視圖或在運行時串聯值,但有些這裏有一些探索性的問題:

  1. 有多少行是dbo.Table3(基表反對,你會大約有多少串聯值?
  2. 有多少行被串連到每個MyConcatenatedId價值?
  3. 它是如何現在正執行,以及如何快速它需要緩慢?
  4. 每分鐘讀取數/秒這是什麼意思?
  5. dbo.another-tbl在提供的子查詢中似乎沒有做任何事情(也許它在真實版本中)。你需要嗎?它是否需要成爲左連接?

我最初的想法是,如果這需要高性能,而不是,不要使用視圖。如果你必須使用視圖,也許玩索引提示像NOEXPAND你有什麼替代品?

不要序列化:我很難說明高容量數據需要在運行時序列化的場景。如果可能的話,返回的數據集或當它放在序列化數據。

  • 優點
    • 容易在DB側
  • 缺點
    • 可能不適用於有可能你需要做什麼

堅持的表格/儘早工作:可能也需要觸發器,但是當底層數據發生變化時,將其寫入持久表並從中讀取。或者排隊的改變類似Change Data Capture,那麼這些變化異步工作

  • 優點
    • 快速從
  • 缺點閱讀
    • 疼痛,保持和觸發器可加繁重的開銷

程序:除非您需要每次調用的所有數據,否則請考慮製作一個可以參數化的過程,以便只在需要時才提取所需的內容。一個視圖僅限於一個查詢,並且關於該複雜性的查詢的統計信息可能很快變成垃圾。一個過程可以單獨地將語句和更小的塊分開,這樣您可以更頻繁地獲得一致且更快的計劃。

  • 優點
    • 更可自定義比視圖和更優化的事情可以做
  • 缺點
    • 不能直接對它們進行查詢(雖然我不認爲這是不使用它們的好理由)