在 SQL Server 2008 中使用 FOR XML PATH 提高 SQL 查询的性能
Posted
技术标签:
【中文标题】在 SQL Server 2008 中使用 FOR XML PATH 提高 SQL 查询的性能【英文标题】:Improve performance of SQL query with a FOR XML PATH in SQL Server 2008 【发布时间】:2018-04-17 01:28:34 【问题描述】:我正在尝试使用 For XML 路径为用户连接 LoadIds,这是我整个查询的一部分,我验证了在计算这个连接的 LoadId 列时已经过最长时间。下面是语法,有人可以建议一种有效地重写它的方法吗?
SELECT
Col1, col2,
LoadIds = STUFF((SELECT ' , ' + CAST([LoadId] AS varchar(5))
FROM Table1 AS t1
WHERE t1.[UserId] = [t2].[UserId]
FOR XML PATH ('')), 1, 2, '')
FROM
Table1 AS t2
GROUP BY
[UserId]
【问题讨论】:
性能对您来说到底是什么问题?这看起来像是 SQL Server 中一个非常典型的FOR XML PATH
查询。你有UserId
的索引吗?
@TimBiegeleisen 如果我评论 LoadIds 的计算,查询的性能在 20 秒内,而使用 LoadIds 最多可以达到一分钟。我没有关于 UserId 的索引,也没有创建权限
@Naina... 发布的查询中有错字吗?因为我在group by
子句中只看到userid
,但select
语句没有expression
。
如果您没有创建索引的权限,这可能对您没有帮助,但有机会使用CLR function。
@Naina,这个对SQL CLR也不错GROUP_CONCAT
【参考方案1】:
1)。我会尝试在临时表或表变量中收集所需的数据,在其上创建索引,然后使用连接。
2)。 FOR XML PATH 适用于小型记录集,对于大型记录集我会尝试递归。
declare @T table (
UserId int not null,
RowNumber int not null,
LoadId varchar(5) not null
primary key clustered (UserId, RowNumber)
);
insert into @T
select
UserId,
row_number() over(partition by UserId order by LoadId),
CAST(LoadId AS varchar(5))
from
Table1 ;
with cte (UserId, RowNumber, LoadIds) as
(
select
UserId,
RowNumber,
LoadIds = convert(varchar(8000), LoadId)
from @T
where RowNumber = 1
union all
select
t.UserId,
t.RowNumber,
convert(varchar(8000), cte.LoadIds + ', ' + t.LoadId)
from
cte inner join @T t on t.UserId = cte.UserId and t.RowNumber = cte.RowNumber + 1
)
select UserId, LoadIds = max(LoadIds) from cte group by UserId;
【讨论】:
也许你应该看看这个,sqlperformance.com/2014/08/t-sql-queries/… 但我听到了相反的意见,也看到了其他结果。这就是为什么我写了“我会尝试......” 我通常会随身携带一些备忘单,例如解决此类问题的常用技术,对于分组连接,最好的方法是 xml(您应该牢记一些注意事项)和 CLR。已故 Dwain 营地的精彩读物在这里High perf T SQL code patterns 即使我尝试了 r-cte 几次,直到我遇到了这个。这就是为什么指出它,现在开始你将密切关注 r-cte :) 对于寻求解决方案的其他人,我发现按照@VadimLoboda 的建议在临时表上创建索引确实加快了我的查询速度【参考方案2】:您可以做的一件事是在进行字符串聚合之前选择不同的用户ID:
SELECT t2.UserId,
STUFF((SELECT ' , ' + CAST([LoadId] AS varchar(8000))
FROM Table1 t1
WHERE t1.[UserId] = [t2].[UserId]
FOR xml PATH ('')
), 1, 2, ''
) as LoadIds
FROM (SELECT DISTINCT userId
FROM Table1 t2
) t2;
为了提高性能,table1(UserId, LoadId)
上的索引也会有所帮助。
【讨论】:
感谢您的建议,但没有帮助以上是关于在 SQL Server 2008 中使用 FOR XML PATH 提高 SQL 查询的性能的主要内容,如果未能解决你的问题,请参考以下文章
ORM - 特定于用于 .NET 的 SQL Server 2008+
Eclipse IDE for Java Developers(4.10.0)建立与SQL Server 2008数据库的连接
DbVisualizer 连接 SQL Server 2008配置
Query (SQL Server 2008 Express) 在 SQL Server Management Studio 中有效,但在 Delphi 中使用 ADODB 无效