Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Сохранение 10000 записей в одной процедуре / 25 сообщений из 30, страница 1 из 2
26.05.2020, 08:55
    #39962008
lana92
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
Всем привет, подскажите пожалуйста как сохранить 10000 записей в одной процедуре, как лучше реализовать
через insert в цикле php долго
пытаюсь сохранить данные экг
...
Рейтинг: 0 / 0
26.05.2020, 09:18
    #39962013
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
lana92
Всем привет, подскажите пожалуйста как сохранить 10000 записей в одной процедуре, как лучше реализовать
через insert в цикле php долго
пытаюсь сохранить данные экг
Для сиквела лучше получать данные пакетом (передавая в процедуру параметр типа "таблица", либо используя балк-операции)
Но как это можно реализовать, нужно спрашивать в разделе php
...
Рейтинг: 0 / 0
26.05.2020, 09:19
    #39962014
Glebanski
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
lana92,

В php ни в зуб ногой. Но чисто из теоретических соображений поинтересуюсь : на каждый insert новый connect делаете?

PS : вообще отличный кейс для моего "пыточного аппарата" для студентов :)
...
Рейтинг: 0 / 0
26.05.2020, 09:31
    #39962019
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
lana92
Всем привет, подскажите пожалуйста как сохранить 10000 записей в одной процедуре, как лучше реализовать
через insert в цикле php долго
пытаюсь сохранить данные экг


В php есть библиотека с BulkInsert ? В C# вы набиваете данные в DataSet и делаете ему BulkInsert. Через класс SqlBulkCopy . Посмотрите, есть ли эквивалент под PHP.
...
Рейтинг: 0 / 0
26.05.2020, 09:38
    #39962023
lana92
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
Glebanski,

ну сперва сделал процедуру для insert и каждый раз ее вызывал, и так получалось каждый раз коннектиться при прохождении по циклу, а это не очень.
Потом изменил: собирал в цикле список values и уже разом отправлял insert, но есть ограничение на 1000 записей, можно конечно разделить массив на 10 insert, но мне кажется это тоже совсем не лучшее решение
...
Рейтинг: 0 / 0
26.05.2020, 09:55
    #39962036
crutchmaster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
lana92,

Код где?
Должен быть какой-то bulk insert ковыряй свою библиотеку mssql для пыха.
https://www.php.net/manual/ru/function.sqlsrv-prepare.php
...
Рейтинг: 0 / 0
26.05.2020, 20:24
    #39962493
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
Отдайте все эти 10000 записей в параметр хранимой процедуры в виде xml или json (второе - если сервер 2016+), внутри средствами sql разберите, и вставляйте, сколько душе угодно.
...
Рейтинг: 0 / 0
27.05.2020, 08:09
    #39962656
SQL2008
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
uaggster
Отдайте все эти 10000 записей в параметр хранимой процедуры в виде xml или json (второе - если сервер 2016+), внутри средствами sql разберите, и вставляйте, сколько душе угодно.

Злодей!
...
Рейтинг: 0 / 0
27.05.2020, 08:16
    #39962658
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
uaggster
Отдайте все эти 10000 записей в параметр хранимой процедуры в виде xml или json (второе - если сервер 2016+), внутри средствами sql разберите, и вставляйте, сколько душе угодно.



Партянка из INSERT будет быстрее, чем парзить строки, xml, json.
...
Рейтинг: 0 / 0
27.05.2020, 11:46
    #39962735
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
Притом в начале вставок явно открыть транзакцию, в конце закрыть. Вообще муть какая-то, в этом случае загрузку лучше сделать через файл и утилиту bcp.
...
Рейтинг: 0 / 0
27.05.2020, 12:03
    #39962740
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
a_voronin
Партянка из INSERT будет быстрее, чем парзить строки, xml, json.
А как же время на компиляцию портянки из 10000 insert'ов?
...
Рейтинг: 0 / 0
27.05.2020, 13:19
    #39962778
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
a_voronin
uaggster
Отдайте все эти 10000 записей в параметр хранимой процедуры в виде xml или json (второе - если сервер 2016+), внутри средствами sql разберите, и вставляйте, сколько душе угодно.



Партянка из INSERT будет быстрее, чем парзить строки, xml, json.

Да щас, конечно.
Во первых, чтобы это хоть как то сравнилось по скорости - это нужно обрамить внешней транзакцией, а во вторых оформить сам запрос на вставку как параметризованный.
Кроме того, всё это нужно проделать в одном коннекте.
И даже в этом случае - 10 тыс. вызовов, притом синхронных, с клиента - это та еще песня.

Разница будет раз в 100, в пользу парсинга json или openxml.
...
Рейтинг: 0 / 0
27.05.2020, 15:37
    #39962876
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
uaggster
a_voronin
пропущено...



Партянка из INSERT будет быстрее, чем парзить строки, xml, json.

Да щас, конечно.
Во первых, чтобы это хоть как то сравнилось по скорости - это нужно обрамить внешней транзакцией, а во вторых оформить сам запрос на вставку как параметризованный.
Кроме того, всё это нужно проделать в одном коннекте.
И даже в этом случае - 10 тыс. вызовов, притом синхронных, с клиента - это та еще песня.

Разница будет раз в 100, в пользу парсинга json или openxml.


А вы тест проведите. Я такой делал.

Имеется ввиду парзить XML - JSON, против отправки десятка команд по 1000 INSERT. Речь не идет о выполнении INSERT по одному. BULK INSERT не рассматриваем, ибо он еще быстрее.
...
Рейтинг: 0 / 0
27.05.2020, 16:13
    #39962908
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
a_voronin
А вы тест проведите. Я такой делал.
Покажите как.

Тест
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
use tempdb;
set ansi_nulls, quoted_identifier, xact_abort on;
go

create table dbo.s (id int, a int, b nvarchar(100), c nchar(2000));
go

insert into dbo.s
 (id, a, b, c)
 select top (100000)
  row_number() over (order by 1/0), 1, cast(newid() as nvarchar(100)), replicate(N'a', 2000)
 from
  master.dbo.spt_values a cross join
  master.dbo.spt_values b;
go

select top (0) * into dbo.t1 from dbo.s;
select top (0) * into dbo.t2 from dbo.s;
go

declare @q nvarchar(max), @dt datetime2, @x xml;
declare @result table (descr nvarchar(30), rows_affected bigint, [elapsed_time (ms)] int);

select
 @q = N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;'
from
 (
  select
   N'insert into dbo.t1 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  for xml path(''), type
 ) t(x);

set @dt = sysdatetime();
exec(@q);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'footcloth of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t1;

select
 @x = t.x
from
 (
  select
   id as [@id], a as [@a], b as [@b], c as [@c]
  from
   dbo.s
  for xml path('item'), type
 ) t(x);

set @dt = sysdatetime();
insert into dbo.t2
 (id, a, b, c)
 select
  t.n.value('@id', 'int'),
  t.n.value('@a', 'int'),
  t.n.value('@b', 'nvarchar(100)'),
  t.n.value('@c', 'nchar(2000)')
 from
  @x.nodes('item') t(n);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'xml', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t2;

select * from @result order by [elapsed_time (ms)];
go

drop table dbo.s, dbo.t1, dbo.t2;
go


descrrows_affectedelapsed_time (ms)xml1000002924footcloth of inserts10000017503
...
Рейтинг: 0 / 0
27.05.2020, 16:17
    #39962913
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
Я как-то проводил клиент-серверные тесты, наиболее выгодным оказалась вставка по 800-600 INSERT в пачке и это мало зависело от ширины таблицы по сравнению с XML. Тем не менее, XML оказался форматом с боле простой реализацией и иногда показывал сравнимые результаты.
...
Рейтинг: 0 / 0
27.05.2020, 17:11
    #39962955
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
a_voronin, Владислав Колосов, и какие же были методики тестирования?

Добавим "пачки"
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
use tempdb;
set ansi_nulls, quoted_identifier, xact_abort on;
set nocount on;
go

create table dbo.s (id int, a int, b nvarchar(100), c nchar(2000));
go

insert into dbo.s
 (id, a, b, c)
 select top (100000)
  row_number() over (order by 1/0), 1, cast(newid() as nvarchar(100)), replicate(N'a', 2000)
 from
  master.dbo.spt_values a cross join
  master.dbo.spt_values b;
go

select top (0) * into dbo.t1 from dbo.s;
select top (0) * into dbo.t2 from dbo.s;
select top (0) * into dbo.t3 from dbo.s;
go

declare @q nvarchar(max), @dt datetime2, @x xml;
declare @result table (descr nvarchar(30), rows_affected bigint, [elapsed_time (ms)] int);

select
 @q = N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;'
from
 (
  select
   N'insert into dbo.t1 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  for xml path(''), type
 ) t(x);

declare @t table (q nvarchar(max));

insert into @t
 (q)
select
 b.q
from
 (select top (100) row_number() over (order by 1/0) - 1 from master.dbo.spt_values) a(n) cross apply
 (
  select top (1000)
   N'insert into dbo.t3 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  where
   id > a.n * 1000
  for xml path(''), type
 ) t(x) cross apply
 (select N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;') b(q)
where
 b.q is not null;

set @dt = sysdatetime();
exec(@q);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'footcloth of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t1;

select
 @x = t.x
from
 (
  select
   id as [@id], a as [@a], b as [@b], c as [@c]
  from
   dbo.s
  for xml path('item'), type
 ) t(x);

set @dt = sysdatetime();
insert into dbo.t2
 (id, a, b, c)
 select
  t.n.value('@id', 'int'),
  t.n.value('@a', 'int'),
  t.n.value('@b', 'nvarchar(100)'),
  t.n.value('@c', 'nchar(2000)')
 from
  @x.nodes('item') t(n);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'xml', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t2;

declare t cursor local fast_forward for
 select q from @t;

open t;
set @dt = sysdatetime();

while 1 = 1
 begin
  fetch next from t into @q;
  if @@fetch_status <> 0
   break;

  exec(@q);
 end;
close t;
deallocate t;
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'batches of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t3;

select * from @result order by [elapsed_time (ms)];
go

drop table dbo.s, dbo.t1, dbo.t2, dbo.t3;
go


descrrows_affectedelapsed_time (ms)xml1000003033batches of inserts10000011310footcloth of inserts10000015806
...
Рейтинг: 0 / 0
27.05.2020, 18:07
    #39962977
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
invm,

приложение читало данные из файла, формировало строки INSERT запросов в пачки по заданному количеству строк и выполняло полученный код на сервере до исчерпания строк в источнике. Либо локально формировал XML и отправлял его на сервер во временную процедуру, которую же создавало приложение. Использовал ODBC протокол. Но это было давно, во времена Windows XP.
...
Рейтинг: 0 / 0
27.05.2020, 18:25
    #39962984
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
Владислав Колосов,

Во времена XP все было несколько по-другому...

Более корректный тест
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
use tempdb;
set ansi_nulls, quoted_identifier, xact_abort on;
set nocount on;
go

create table dbo.s (id int, a int, b nvarchar(100), c nchar(2000));
go

insert into dbo.s
 (id, a, b, c)
 select top (100000)
  row_number() over (order by 1/0), 1, cast(newid() as nvarchar(100)), replicate(N'a', 2000)
 from
  master.dbo.spt_values a cross join
  master.dbo.spt_values b;
go

select top (0) * into dbo.t1 from dbo.s;
select top (0) * into dbo.t2 from dbo.s;
select top (0) * into dbo.t3 from dbo.s;
go

declare @q nvarchar(max), @dt datetime2, @sx nvarchar(max), @x xml;
declare @result table (descr nvarchar(30), rows_affected bigint, [elapsed_time (ms)] int);

select
 @q = N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;'
from
 (
  select
   N'insert into dbo.t1 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  for xml path(''), type
 ) t(x);

declare @t table (q nvarchar(max));

insert into @t
 (q)
select
 b.q
from
 (select top (100) row_number() over (order by 1/0) - 1 from master.dbo.spt_values) a(n) cross apply
 (
  select top (1000)
   N'insert into dbo.t3 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  where
   id > a.n * 1000
  for xml path(''), type
 ) t(x) cross apply
 (select N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;') b(q)
where
 b.q is not null;

set @dt = sysdatetime();
exec(@q);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'footcloth of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t1;

select
 @sx = t.x
from
 (
  select
   id as [@id], a as [@a], b as [@b], c as [@c]
  from
   dbo.s
  for xml path('item')--, type
 ) t(x);

set @dt = sysdatetime();

set @x = @sx;
insert into dbo.t2
 (id, a, b, c)
 select
  t.n.value('@id', 'int'),
  t.n.value('@a', 'int'),
  t.n.value('@b', 'nvarchar(100)'),
  t.n.value('@c', 'nchar(2000)')
 from
  @x.nodes('item') t(n);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'xml', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t2;

declare t cursor local fast_forward for
 select q from @t;

open t;
set @dt = sysdatetime();

while 1 = 1
 begin
  fetch next from t into @q;
  if @@fetch_status <> 0
   break;

  exec(@q);
 end;
close t;
deallocate t;
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'batches of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t3;

select * from @result order by [elapsed_time (ms)];
go

drop table dbo.s, dbo.t1, dbo.t2, dbo.t3;
go


descrrows_affectedelapsed_time (ms)xml1000008080batches of inserts10000010239footcloth of inserts10000016092
...
Рейтинг: 0 / 0
27.05.2020, 19:31
    #39963031
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
invm, возможно, через openxml - будет еще быстрее.
...
Рейтинг: 0 / 0
27.05.2020, 20:24
    #39963052
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
uaggster, возможно. Особенно, если столбцов будет много.
...
Рейтинг: 0 / 0
28.05.2020, 07:02
    #39963153
Ennor Tiegael
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
lana92,

Ваш случай , практ. один в один. Тоже с пхп, опять-таки.

Ну и вроде уже обсуждали производительность альтернативных вариантов такой вставки, table type обгоняет всех, кроме bulk insert.
...
Рейтинг: 0 / 0
28.05.2020, 09:16
    #39963187
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
invm
a_voronin, Владислав Колосов, и какие же были методики тестирования?

Добавим "пачки"
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
use tempdb;
set ansi_nulls, quoted_identifier, xact_abort on;
set nocount on;
go

create table dbo.s (id int, a int, b nvarchar(100), c nchar(2000));
go

insert into dbo.s
 (id, a, b, c)
 select top (100000)
  row_number() over (order by 1/0), 1, cast(newid() as nvarchar(100)), replicate(N'a', 2000)
 from
  master.dbo.spt_values a cross join
  master.dbo.spt_values b;
go

select top (0) * into dbo.t1 from dbo.s;
select top (0) * into dbo.t2 from dbo.s;
select top (0) * into dbo.t3 from dbo.s;
go

declare @q nvarchar(max), @dt datetime2, @x xml;
declare @result table (descr nvarchar(30), rows_affected bigint, [elapsed_time (ms)] int);

select
 @q = N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;'
from
 (
  select
   N'insert into dbo.t1 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  for xml path(''), type
 ) t(x);

declare @t table (q nvarchar(max));

insert into @t
 (q)
select
 b.q
from
 (select top (100) row_number() over (order by 1/0) - 1 from master.dbo.spt_values) a(n) cross apply
 (
  select top (1000)
   N'insert into dbo.t3 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  where
   id > a.n * 1000
  for xml path(''), type
 ) t(x) cross apply
 (select N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;') b(q)
where
 b.q is not null;

set @dt = sysdatetime();
exec(@q);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'footcloth of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t1;

select
 @x = t.x
from
 (
  select
   id as [@id], a as [@a], b as [@b], c as [@c]
  from
   dbo.s
  for xml path('item'), type
 ) t(x);

set @dt = sysdatetime();
insert into dbo.t2
 (id, a, b, c)
 select
  t.n.value('@id', 'int'),
  t.n.value('@a', 'int'),
  t.n.value('@b', 'nvarchar(100)'),
  t.n.value('@c', 'nchar(2000)')
 from
  @x.nodes('item') t(n);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'xml', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t2;

declare t cursor local fast_forward for
 select q from @t;

open t;
set @dt = sysdatetime();

while 1 = 1
 begin
  fetch next from t into @q;
  if @@fetch_status <> 0
   break;

  exec(@q);
 end;
close t;
deallocate t;
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'batches of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t3;

select * from @result order by [elapsed_time (ms)];
go

drop table dbo.s, dbo.t1, dbo.t2, dbo.t3;
go


descrtrows_affectedtelapsed_time (ms)xmlt100000t3033batches of insertst100000t11310footcloth of insertst100000t15806


Я тестировал пуская запрос из клиентской тулзы. Дело было на 2005 и давно.

Ваш тест показывает, что из xml вставляется быстрее, но этот тест не совсем тот случай, который у ТС, у который был у меня. Отсутствует один шаг -- xml приходит в текстовом виде и должен быть сначала распарзен. У вас же на входе подготовленный xml: @x xml;.
...
Рейтинг: 0 / 0
28.05.2020, 09:55
    #39963204
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
a_voronin
Отсутствует один шаг -- xml приходит в текстовом виде и должен быть сначала распарзен.
Смотрите последнюю версию теста.
...
Рейтинг: 0 / 0
29.05.2020, 18:46
    #39964213
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
В общем, из строковых вариантов - самый быстрый json, как и ожидалось.
А вот то, что OPENXML оказался медленнее XQuery - для меня неожиданность.


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
use tempdb;
set ansi_nulls, quoted_identifier, xact_abort on;
set nocount on;
go

create table dbo.s (id int, a int, b nvarchar(100), c nchar(2000));
go

insert into dbo.s
 (id, a, b, c)
 select top (100000)
  row_number() over (order by 1/0), 1, cast(newid() as nvarchar(100)), replicate(N'a', 2000)
 from
  master.dbo.spt_values a cross join
  master.dbo.spt_values b;
go

select top (0) * into dbo.t1 from dbo.s;
select top (0) * into dbo.t2 from dbo.s;
select top (0) * into dbo.t3 from dbo.s;
select top (0) * into dbo.t4 from dbo.s;
select top (0) * into dbo.t5 from dbo.s;
go

declare @q nvarchar(max), @dt datetime2, @sx nvarchar(max), @x xml, @sj nvarchar(max), @s nvarchar(max);
declare @result table (descr nvarchar(30), rows_affected bigint, [elapsed_time (ms)] int);

select
 @q = N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;'
from
 (
  select
   N'insert into dbo.t1 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  for xml path(''), type
 ) t(x);

declare @t table (q nvarchar(max));

insert into @t
 (q)
select
 b.q
from
 (select top (100) row_number() over (order by 1/0) - 1 from master.dbo.spt_values) a(n) cross apply
 (
  select top (1000)
   N'insert into dbo.t3 (id, a, b, c) values (' + cast(id as nvarchar(10)) + N', ' + cast(a as nvarchar(10)) + N', ''' + b + ''', ''' + c + ''');' 
  from
   dbo.s
  where
   id > a.n * 1000
  for xml path(''), type
 ) t(x) cross apply
 (select N'begin tran; ' + t.x.value('.', 'nvarchar(max)') + N' commit;') b(q)
where
 b.q is not null;

set @dt = sysdatetime();
exec(@q);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'footcloth of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t1;

select
 @sx = t.x
from
 (
  select
   id as [@id], a as [@a], b as [@b], c as [@c]
  from
   dbo.s
  for xml path('item')--, type
 ) t(x);

set @dt = sysdatetime();

set @x = @sx;
insert into dbo.t2
 (id, a, b, c)
 select
  t.n.value('@id', 'int'),
  t.n.value('@a', 'int'),
  t.n.value('@b', 'nvarchar(100)'),
  t.n.value('@c', 'nchar(2000)')
 from
  @x.nodes('item') t(n);
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'xml', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t2;

set @x = NULL;

set @dt = sysdatetime();

declare @i as int;
set @x = '<root>' + @sx + '</root>';
exec sp_xml_preparedocument @i output, @x;

insert into dbo.t4
 (id, a, b, c)
 select id, a, b, c
 FROM OPENXML (@i, '/root/item', 1) 
				With (id int '@id',
					  a int '@a',
					  b  nvarchar(100) '@b',
					  c  nchar(2000) '@c'
				);
exec sp_xml_removedocument @i

insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'OPENXML', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t4;

select
 @sj = t.x
from
 (
  select
   id as [id], a as [a], b as [b], c as [c]
  from
   dbo.s
  for json auto
 ) t(x);

set @dt = sysdatetime();

set @s = @sj;
insert into dbo.t5
 (id, a, b, c)
 select  id, a, b, c
 FROM OPENJSON (@s) 
				With (id int '$.id',
					  a int '$.a',
					  b  nvarchar(100) '$.b',
					  c  nchar(2000) '$.c'
				);

insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'json', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t5;

declare t cursor local fast_forward for
 select q from @t;

open t;
set @dt = sysdatetime();

while 1 = 1
 begin
  fetch next from t into @q;
  if @@fetch_status <> 0
   break;

  exec(@q);
 end;
close t;
deallocate t;
insert into @result
 (descr, rows_affected, [elapsed_time (ms)])
 select N'batches of inserts', count(*), datediff(ms, @dt, sysdatetime()) from dbo.t3; 

select * from @result order by [elapsed_time (ms)];
go

drop table dbo.s, dbo.t1, dbo.t2, dbo.t3, dbo.t4, dbo.t5;
go




descr rows_affected elapsed_time (ms)json 100000 5992xml 100000 8498batches of inserts 100000 14162OPENXML 100000 16069footcloth of inserts 100000 25186
...
Рейтинг: 0 / 0
29.05.2020, 19:31
    #39964225
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Сохранение 10000 записей в одной процедуре
uaggster
В общем, из строковых вариантов - самый быстрый json, как и ожидалось.
А вот то, что OPENXML оказался медленнее XQuery - для меня неожиданность.

descr rows_affected elapsed_time (ms)json 100000 5992xml 100000 8498batches of inserts 100000 14162OPENXML 100000 16069footcloth of inserts 100000 25186

Ээээ, горе-тестировщики, а сборку JSON-XML выполняет дух святой?
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Сохранение 10000 записей в одной процедуре / 25 сообщений из 30, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]