2017-05-25 103 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那么这也会有所帮助。