如何用大数据集提高FOR XML PATH的性能

问题描述 投票:2回答:2

我试图使用FOR XML PATH技术连接结果集中的字符串,但遇到了一些性能问题。我想知道是否有任何方法可以改进这种类型的查询。

我正在编写一个报告查询,用于检查Part表的所有15000行的库存余额。这些部件可用于存储在Equipment表中的一件或多件设备,该表还有大约12000行。客户希望报告具有逗号分隔的设备,其中每个部件都使用这些设备。

我首先创建了一个返回零件和设备的完整连接的查询

SELECT PartName, Balance, EquipmentName as UsedOn 
FROM Part p
    LEFT OUTER JOIN EquipmentPart ep ON p.PartID = ep.PartID
    LEFT INNER JOIN Equipment e ON ep.EquipmentID = e.EquipmentID

这将在1秒内返回49000行的结果集(根据SQL Server Management Studio),但未完成最终目标。

然后我尝试通过执行以下操作来专注于获取逗号分隔字段

SELECT PartName, Balance, 
      STUFF((SELECT ',' + EquipmentName
        FROM Equipment e JOIN EquipmentPart ep ON e.EquipmentID = ep.EquipmentID
        WHERE ep.PartID = p.PartID
        FOR XML PATH('')) as UsedOn
FROM Part p

这花了8分多钟才终于杀了它;它只通过了15000行中的8000个。

我当前的解决方案将第一个查询与FOR XML PATH子查询相结合

WITH PartBalances AS
(SELECT PartID, PartName, Balance, EquipmentName as UsedOn 
FROM Part p
    LEFT OUTER JOIN EquipmentPart ep ON p.PartID = ep.PartID
    LEFT INNER JOIN Equipment e ON ep.EquipmentID = e.EquipmentID
)
SELECT PartName, Balance,
       STUFF ((SELECT ',' + UsedOn
        FROM PartBalances p2
        WHERE p1.PartID = p2.PartID
        FOR XML PATH(''))
FROM PartBalances p1
GROUP BY PartID, PartName, Balance

这似乎回归了我想要的,但它需要一分钟。一分钟是可以接受的,但我希望能有更好的东西。

有什么我做错了或愚蠢的吗?有没有办法避免制作15000个子查询?

sql sql-server aggregate-functions sqlperformance
2个回答
0
投票

你能尝试运行这个版本的查询吗?

SELECT PartName, Balance, 
       STUFF((SELECT ',' + EquipmentName
              FROM EquipmentPart ep JOIN
                   Equipment e
                   ON e.EquipmentID = ep.EquipmentID
              WHERE ep.PartID = p.PartID
              FOR XML PATH('')
             ), 1, 1, '') as UsedOn
FROM Part p;

LEFT JOIN可能会使优化器混乱。


0
投票
WITH PartBalances AS
(SELECT PartID, PartName, Balance, EquipmentName as UsedOn 
FROM Part p
    JOIN EquipmentPart ep ON p.PartID = ep.PartID
    JOIN Equipment e ON ep.EquipmentID = e.EquipmentID
)
SELECT PartName, Balance,
       STUFF ((SELECT ',' + UsedOn
        FROM PartBalances p2
        WHERE p1.PartID = p2.PartID
        FOR XML PATH(''))
FROM PartBalances p1
GROUP BY PartID, PartName, Balance
© www.soinside.com 2019 - 2024. All rights reserved.