2017-05-25 135 views
1

我的任務是重新處理一組現有的舊查詢。我能找到的主要問題是它們都使用XML PATH()在返回結果之前更新各種臨時表。SQL Server 2012:XML的替代路徑

它如此分解,我們創建一個臨時表,其基本信息爲不同的值。

OwnerId | FName | LName | Pets 
--------+-------+-------+------- 
PA1234 | Greg | Brady | 
ZB0013 | Peter | Brady | 
QX9999 | Bobby | Brady | 

然後這個表需要從一個非常大的表 - 數百萬條記錄更新。這表看起來是這樣的:

PetId | OwnerId | PetType 
------+---------+----------- 
100 | PA1234 | cat 
101 | PA1234 | dog, bird 
103 | PA1234 | gerbil 
104 | ZB0013 | fish 
105 | QX9999 | dog, cat 
106 | QX9999 | dog, bird 
107 | AA5555 | snake 

預期的結果會是這個樣子:

OwnerId | FName | LName | Pets 
--------+-------+-------+------------------------- 
PA1234 | Greg | Brady | cat; dog, bird; gerbil 
ZB0013 | Peter | Brady | fish 
QX9999 | Bobby | Brady | dog, cat; dog, bird 

,因爲它代表產生預期的效果,但需要FOREVER查詢。 100條記錄需要將近5分鐘才能返回結果,這對我來說似乎很瘋狂。

UPDATE #Temp 
SET Pets = STUFF((SELECT DISTINCT '; ' + P1.PetType 
        FROM Pet_Table P1 
        WHERE P1.OwnerID = OuterT.OwnerId 
        FOR XML PATH('')), 1, 1, '') 
FROM #Temp OuterT 

我覺得像COALESCE會更快,但無法弄清楚如何使它在這種情況下工作,可能是CTE,我要找的任何建議。

謝謝,讓我知道是否需要更多的信息或我需要更好地解釋的東西。

+3

您是否通過查看計劃確定FOX XML PATH確實是問題所在?你在其他表上有適當的索引嗎? – pmbAustin

+0

@pmbAustin我認爲FOR XML PATH是個問題。我運行查詢W/O XML PATH,它需要約5秒鐘。使用XML PATH需要5分鐘。 –

+1

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

回答

0

您是否通過查看計劃確定FOX XML PATH確實是問題所在?你在其他表上有適當的索引嗎?

FOR XML PATH通常具有很高的性能,我從來沒有見過它會導致您在此處確定的範圍降級。我會看看這些計劃,並深入瞭解哪些索引正在使用(或未正在使用),並查看是否調整索引(添加INCLUDE列)或添加新索引可能會解決您的問題。

2

五分鐘100記錄太慢。我懷疑你可能永遠不會得到你真正想要的表演。但是,索引將有所幫助。

首先,您需要正確地短語查詢。您需要在UPDATE中指定OuterT - 因爲對#Temp的兩個引用是不同的。你的版本本質上是做一個CROSS JOIN

UPDATE OuterT 
    SET Pets = STUFF((SELECT DISTINCT '; ' + P1.PetType 
         FROM Pet_Table P1 
         WHERE P1.OwnerID = OuterT.OwnerId 
         FOR XML PATH('') 
        ), 1, 1, '') 
    FROM #Temp OuterT; 

然後,你要索引。對於此查詢:Pet_Table(OwnerId, PetType)

此外,如果你可以擺脫SELECT DISTINCT那麼這也會有所幫助。