Уничтожение XML с помощью node () / value () в SQL Server приводит к проблемам с производительностью при запросе большого количества столбцов.Для каждого столбца существует одно объединение вложенных циклов с вызовом функции xml.
План запроса с 3 столбцами:

План запроса с 5 столбцами:

Только представьте, как это будет выглядеть с более чем 150 столбцами.
Другой вариант для вас - использовать OPENXML .У него нет тех же проблем со многими столбцами.
Ваш запрос будет выглядеть примерно так:
declare @H int;
declare @X xml;
exec sys.sp_xml_preparedocument @H output,
@X;
select C1,
C2,
C3
from
openxml(@H, 'Table/row', 0)
with (
C1 int,
C2 int,
C3 int
);
exec sys.sp_xml_removedocument @H;
Для меня использование 150 столбцов и 1000 строк заняло около 14 секунд с узлами () / значение () и 3 секунды с OPENXML.
Голосование за изменение.
Код, использованный для тестирования;
drop table T;
go
declare @C int = 150;
declare @S nvarchar(max);
declare @X xml;
declare @N int = 1000;
declare @D datetime;
set @S = 'create table T('+
stuff((
select top(@C) ', '+N'C'+cast(row_number() over(order by 1/0) as nvarchar(3)) + N' int'
from sys.columns
for xml path('')
), 1, 2, '') + ')'
exec sp_executesql @S;
set @S = 'insert into T select top(@N) '+
stuff((
select top(@C) ',1'
from sys.columns as c1
for xml path('')
), 1, 1, '') + ' from sys.columns as c1, sys.columns as c2';
exec sp_executesql @S, N'@N int', @N;
set @X = (
select *
from dbo.T
for xml raw, root('Table')
);
set @S = 'select '+
stuff((
select top(@C) ', '+N'T.X.value(''@C'+cast(row_number() over(order by 1/0) as nvarchar(3)) + N''', ''int'')'
from sys.columns
for xml path('')
), 1, 2, '') + ' from @X.nodes(''Table/row'') as T(X)'
set @D = getdate();
exec sp_executesql @S, N'@X xml', @X;
select datediff(second, @D, getdate());
set @S = 'declare @H int;
exec sp_xml_preparedocument @H output, @X;
select *
from openxml(@H, ''Table/row'', 0)
with (' +
stuff((
select top(@C) ', C'+cast(row_number() over(order by 1/0) as nvarchar(3))+ ' int'
from sys.columns
for xml path('')
), 1, 2, '') + ');
exec sys.sp_xml_removedocument @H';
set @D = getdate();
exec sp_executesql @S, N'@X xml', @X
select datediff(second, @D, getdate());