SQL Server 比“CONCAT”或“+”更有效的连接长字符串的方法(varchar(max))

at0kjp5o  于 2022-11-28  发布在  其他
关注(0)|答案(2)|浏览(158)

我们正在开发一个需要大量数据的软件产品,我们试图找到连接3个字符串的最有效的方法。我们使用了最常见的方法来连接字符串,如“+”运算符或“CONCAT”函数。当我使用“+”运算符时,我的查询将如下所示:

declare @S1 varchar(max)
 declare @s2 varchar(max)
 declare @s varchar(max)
 declare @lni int 
 set @lni = 0 

 set @s = cast('' as varchar(max))
 set @S1 = cast('TEST' as varchar(max))
 set @s2 = cast(' OK' as varchar(max))

while (@lni <100000) begin 
   set @lni = @lni+1
   set @S =@s+ @S1+ @s2

 end 
 print len(@S)
 print @S

使用“Concat”函数,我的查询将看起来像这样:

declare @S1 varchar(max)
 declare @s2 varchar(max)
 declare @s varchar(max)
 declare @lni int 
 set @lni = 0 

 set @s = cast('' as varchar(max))
 set @S1 = cast('TEST' as varchar(max))
 set @s2 = cast(' OK' as varchar(max))

while (@lni <100000) begin 
   set @lni = @lni+1
   set @S =concat(@S,@S1,@S2)

 end 
 print len(@S)
 print @S

SSMS在2分30秒内执行了使用“+”运算符的查询,在1分18秒内执行了使用“CONCAT”函数的查询。我还必须提到,我用“10000000 "替换了”100000",在5个多小时内执行了该查询。我很好奇我们是否可以找到更快的执行方法。

mspsb9vt

mspsb9vt1#

尝试使用计数表执行以下非循环等效操作:

declare @s varchar(max) = '', @s1 varchar(max) = 'TEST', @s2 varchar(max) = ' OK';
 with 
    l0 as (select 0 v from (values(0),(0),(0),(0),(0))v(v)), 
    l1 as (select 1 v from l0 a cross join l0 b),
    l2 as (select 2 v from l1 a cross join l1 b),
    l3 as (select 3 v from l2 a cross join l2 b),
    l4 as (select 4 v from l3 a cross join l3 b),
    n  as (select n = Row_Number() over(order by @@spid) from l4)

    select top (100000) 
    @s = string_agg(concat(@s1, @s2),'') 
    from n;

    print @s;

在我的测试中,做100,000个concat需要2秒,我不能告诉你你的循环版本需要多长时间,因为它还没有完成。
请参阅Demo Fiddle

bxpogfeg

bxpogfeg2#

还可以使用递归CTE和FOR XML PATH

declare @S1 varchar(max)
 declare @s2 varchar(max)
 declare @s varchar(max)
 declare @lni int 
 set @lni = 0 

 set @s = cast('' as varchar(max))
 set @S1 = cast('TEST' as varchar(max))
 set @s2 = cast(' OK' as varchar(max))
 ;

 WITH CTE AS 
 (
    SELECT concat(@S,@S1,@S2) s, @lni as i
    UNION ALL
    SELECT s,i+1 FROM CTE
    WHERE i<99999
)
Select @S = 
( 
    SELECT S AS [text()]
    FROM CTE
    FOR XML PATH ('')
)
OPTION (MAXRECURSION 0);

print len(@S)
print @S

相关问题