Sempre pensei que a função CONCAT fosse na verdade um wrapper sobre o + (Concatenação de Strings) com algumas verificações adicionais para facilitar nossa vida.
Não encontrei nenhum detalhe interno sobre como as funções são implementadas. Quanto ao desempenho, parece que há sobrecarga para chamar CONCAT
quando os dados estão concatenando em um loop (o que parece normal, pois há identificadores adicionais para NULLs).
Há poucos dias, um desenvolvedor modificou algum código de concatenação de strings (de +
para CONCAT)
porque não gostou da sintaxe e me disse que ficou mais rápido.
Para verificar o caso, usei o seguinte código:
DECLARE @V1 NVARCHAR(MAX)
,@V2 NVARCHAR(MAX)
,@V3 NVARCHAR(MAX);
DECLARE @R NVARCHAR(MAX);
SELECT @V1 = REPLICATE(CAST('V1' AS NVARCHAR(MAX)), 50000000)
,@V2 = REPLICATE(CAST('V2' AS NVARCHAR(MAX)), 50000000)
,@V3 = REPLICATE(CAST('V3' AS NVARCHAR(MAX)), 50000000);
onde esta é a variante um:
SELECT @R = CAST('' AS NVARCHAR(MAX)) + '{some small text}' + ISNULL(@V1, '{}') + ISNULL(@V2, '{}') + ISNULL(@V3, '{}');
SELECT LEN(@R); -- 1200000017
e esta é a variante dois:
SELECT @R = CONCAT('{some small text}',ISNULL(@V1, '{}'), ISNULL(@V2, '{}'), ISNULL(@V3, '{}'))
SELECT LEN(@R); -- 1200000017
Para strings menores, não há diferenças. Em algum momento, a CONCAT
variante se torna mais rápida:
Eu me pergunto se alguém pode compartilhar alguns detalhes internos ou explicar o comportamento, pois parece que pode haver uma regra de que é melhor concatenar strings grandes usando CONCAT
.
Versão:
Microsoft SQL Server 2022 (RTM-CU8) (KB5029666) - 16.0.4075.1 (X64) 23 de agosto de 2023 14:04:50 Copyright (C) 2022 Microsoft Corporation Standard Edition (64 bits) no Windows Server 2019 Standard 10.0 (Build 17763 : ) (Hipervisor)
O script exato é semelhante ao seguinte:
DECLARE @V1 NVARCHAR(MAX)
,@V2 NVARCHAR(MAX)
,@V3 NVARCHAR(MAX);
DECLARE @R NVARCHAR(MAX);
SELECT @V1 = REPLICATE(CAST('V1' AS NVARCHAR(MAX)), 50000000)
,@V2 = REPLICATE(CAST('V2' AS NVARCHAR(MAX)), 50000000)
,@V3 = REPLICATE(CAST('V3' AS NVARCHAR(MAX)), 50000000);
--SELECT @R = CAST('' AS NVARCHAR(MAX)) + '{some small text}' + ISNULL(@V1, '{}') + ISNULL(@V2, '{}') + ISNULL(@V3, '{}'); -- 00:00:45 -- 00:01:22 -- 00:01:20
--SELECT LEN(@R); -- 300000017
SELECT @R = CONCAT('{some small text}',ISNULL(@V1, '{}'), ISNULL(@V2, '{}'), ISNULL(@V3, '{}')) -- 00:00:11 -- 00:00:16 -- 00:00:10
SELECT LEN(@R); -- 300000017
onde estou alterando o último argumento das funções REPLICATE para gerar strings maiores para a concatenação. Então, estou executando cada variante três vezes.