powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Сравнение СУБД [игнор отключен] [закрыт для гостей] / Быстрое создание записей в БД
7 сообщений из 57, страница 3 из 3
Быстрое создание записей в БД
    #36554753
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да, так
у Вас должно получится быстрее
...
Рейтинг: 0 / 0
Быстрое создание записей в БД
    #36555384
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вставка с учётом ранее введённых данных
Код: plaintext
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.
Class del.e Extends %Persistent
{

Property Value As %BigInt(MINVAL =  1 ) [ InitialExpression =  1 , Required ];

ClassMethod FillSQL(ACount As %Integer = {1e3}) As %Status
{
 set t1 = $ZHOROLOG
 do ##class(del.e).%KillExtent()
 set ^del.eD = - 1  ;первичный ключ начинаем с  0 
 do DISABLE^%NOJRN ;отключаем для сессии журналирование
 ;TSTART
 &sql(insert into del.e default values)
 for i =  1 : 1 :ACount- 1  {
   set id1 = $random(i)
   set id2 = $random(i)
   set id3 = $random(i)
  
   &sql(select %NOLOCK Value into :val1 from del.e where %ID=:id1)
   &sql(select %NOLOCK Value into :val2 from del.e where %ID=:id2)
   &sql(select %NOLOCK Value into :val3 from del.e where %ID=:id3)
   &sql(insert %NOCHECK %NOLOCK %NOINDEX %NOTRIGGER into del.e(Value) values(:val1+:val2+:val3))

   ; или &sql(insert into del.e(Value) select sum(Value) from del.e where %ID in (:id1,:id2,:id3))
    
 }
 do ENABLE^%NOJRN
 ;TCOMMIT
 write "Ввод данных = ",($ZHOROLOG - t1)," с.",!
 quit $$$OK
}

ClassMethod FillDirect(ACount As %Integer = {1e3}) As %Status
{
 set time = $ZHOROLOG
 do ##class(del.e).%KillExtent()
 ;do DISABLE^%NOJRN
 TSTART
 
 set ^del.eD( 0 ) = $ListBuild("", 1 )
 for i =  1 : 1 :ACount- 1  {

   s ^del.eD(i) = $lb("",$li(^del.eD($r(i)), 2 ) + $li(^del.eD($r(i)), 2 ) + $li(^del.eD($r(i)), 2 ))

   /* или
   set id1 = $random(i)
   set id2 = $random(i)
   set id3 = $random(i)
   set val1 = $list(^del.eD(id1),2)
   set val2 = $list(^del.eD(id2),2)
   set val3 = $list(^del.eD(id3),2)
   set ^del.eD(i) = $ListBuild("",val1 + val2 + val3)
   */
 }
 set ^del.eD = ACount- 1 
 ;do ENABLE^%NOJRN
 TCOMMIT
 write "Ввод данных = ",($ZHOROLOG - time)," с.",!
 quit $$$OK
}
}
Результаты:
Код: plaintext
1.
2.
FillSQL(1e6):  28 . 7  с. -  30 . 1  с. (без транзакции/журналирования - с транз./журнал.)
FillDirect(1e6):  12 . 4  с. -  12 . 8  с. (без транз./журнал. - с транз./журнал.)

Подсчёт общей суммы
Код: plaintext
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.
Class del.f Extends %Persistent
{

Property m As %BigInt [ Required ];

Property s1 As del.f [ Required ];

Property s2 As del.f [ Required ];

Property s3 As del.f [ Required ];

ClassMethod Fill(
  ACount As %Integer = {1e6},
  ARnd As %Boolean =  0 ) As %Status
{
 set time = $ZHOROLOG
 do ##class(del.f).%KillExtent()
 do DISABLE^%NOJRN
 set ^del.fD = - 1 
 if ARnd =  0  {
   for i =  0 : 1 :ACount- 1  {
     set ^del.fD(i) = $listbuild("",i+ 1 ,i,i,i)
   }
 } else {
   for i =  0 : 1 :ACount- 1  {
     set ^del.fD(i) = $listbuild("",i+ 1 ,$random(ACount),$random(ACount),$random(ACount))
   }
 }
 set ^del.fD = ACount- 1 
 do ENABLE^%NOJRN
 write "Ввод данных = ",($ZHOROLOG - time)," с.",!
 quit $$$OK
}

/// Хранимая процедура SPQuery1 равнозначна SPQuery2, но удобней в написании благодаря объектному расширению SQL
Query SPQuery1() As %SQLQuery(ROWSPEC="Результат:%BigInt") [SqlProc]
{
  SELECT sum(s1->m + s2->m + s3->m) FROM del.f
}

Query SPQuery2() As %SQLQuery(ROWSPEC="Результат:%BigInt") [SqlProc]
{
  SELECT sum(t1.m + t2.m + t3.m)
  from del.f t
  join del.f t1 on t1.id = t.s1
  join del.f t2 on t2.id = t.s2
  join del.f t3 on t3.id = t.s3
}

ClassMethod SPQuery3() As %BigInt [SqlProc]
{
  set result =  0 
  for i =  0 : 1 :^del.fD {
    set s1 = $list(^del.fD(i), 3 )
    set s2 = $list(^del.fD(i), 4 )
    set s3 = $list(^del.fD(i), 5 )
    set m1 = $list(^del.fD(s1), 2 )
    set m2 = $list(^del.fD(s2), 2 )
    set m3 = $list(^del.fD(s3), 2 )
    set result = result + m1 + m2 + m3
  }
  quit result
}
}
Результаты:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
TEST>d ##class(del.f).Fill()
Ввод данных = . 459627  с.

call del.f_SPQuery1():  5 . 7  с.
select del.f_SPQuery3() from del.f where id= 0 :  1 . 8  с.

TEST>d ##class(del.f).Fill(, 1 )
Ввод данных =  2 . 526582  с.

call del.f_SPQuery1():  16 . 8  с.
select del.f_SPQuery3() from del.f where id= 0 :  12  с.
Возможно, у меня жесткий диск медленно выполняет random access.
...
Рейтинг: 0 / 0
Быстрое создание записей в БД
    #36556298
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного удалось улучшить результат, распараллелив запрос в несколько потоков, вернее процессов:
Распараллеленный запрос
Код: plaintext
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.
...
ClassMethod SPQuery3(nThread As %Integer(VALUELIST=",1,2,4,5,8,10") =  2 ) As %BigInt [ SqlProc ]
{
  quit:($listfind($listbuild( 1 , 2 , 4 , 5 , 8 , 10 ),nThread)= 0 ) - 1 
  kill ^CacheTempUser($job)

  set result= 0 ,k=^del.fD+ 1 \nThread
  
  for i= 1 : 1 :nThread job ..Thread(i- 1 *k,i*k- 1 ,i,$job)

  for i= 1 : 1 :nThread {
    for  quit:$data(^CacheTempUser($job,i))
    set result=result+^CacheTempUser($job,i)
  }

  quit result
}

ClassMethod Thread(i1,i2,n,j) [ServerOnly =  1 ]
{
  set result= 0 
  for i=i1: 1 :i2 set result=result+$li(^del.fD($li(^del.fD(i), 3 )), 2 )+$li(^del.fD($li(^del.fD(i), 4 )), 2 )+$li(^del.fD($li(^del.fD(i), 5 )), 2 )
  // или &sql(select sum(s1->m + s2->m + s3->m) into :result FROM del.f where %ID between :i1 and :i2)
  set ^CacheTempUser(j,n)=result
}
...
Результат:
Код: plaintext
select del.f_SPQuery3( 8 ) from del.f where id= 0 :  7 . 9  с.
...
Рейтинг: 0 / 0
Быстрое создание записей в БД
    #37043837
Alexander Ryndin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Oracle 11R2:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
 declare
    numrec number := 100000 ;
    type tab_type is table of number;
    tab1 tab_type:=tab_type();
    tab2 tab_type:=tab_type();
    tab3 tab_type:=tab_type();
BEGIN
    tab1.extend(numrec);
    tab2.extend(numrec);
    tab3.extend(numrec);
    for ii in  1 ..numrec loop
    tab1(ii):=( 1000  + ii) mod  10000 ;
    tab2(ii):=( 1002  + ii) mod  10000 ;
    tab3(ii):=( 1010   + ii) mod  10000 ;
   end loop;
    forall ii in  1 ..numrec
          INSERT INTO TestA (a,b,c) VALUES (tab1(ii),tab2(ii),tab3(ii));
    commit;
END;
/

PL/SQL procedure successfully completed.
Elapsed: 00:00:00.34
...
Рейтинг: 0 / 0
Быстрое создание записей в БД
    #37045520
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Ryndin,

Там была опечаточка к коде: numrec number :=100000 1000000;
И Все измерения я проводил в виртуалке. Скорость в ней падает вдвое (минимум).
Причем на обычном ноуте среднего класса, а не продакшн сервере )
...
Рейтинг: 0 / 0
Быстрое создание записей в БД
    #37045891
Alexander Ryndin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglAlexander Ryndin,

Там была опечаточка к коде: numrec number :=100000 1000000;
И Все измерения я проводил в виртуалке. Скорость в ней падает вдвое (минимум).
Причем на обычном ноуте среднего класса, а не продакшн сервере )У меня обычный офисный ноут. Настройки Oracle по default - наверняка еще что-то можно подтюнить. С исправленным результатом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
 declare
    numrec number := 1000000 ;
    type tab_type is table of number;
    tab1 tab_type:=tab_type();
    tab2 tab_type:=tab_type();
    tab3 tab_type:=tab_type();
BEGIN
    tab1.extend(numrec);
    tab2.extend(numrec);
    tab3.extend(numrec);
    for ii in  1 ..numrec loop
    tab1(ii):=( 1000  + ii) mod  10000 ;
    tab2(ii):=( 1002  + ii) mod  10000 ;
    tab3(ii):=( 1010   + ii) mod  10000 ;
   end loop;
    forall ii in  1 ..numrec
          INSERT INTO TestA (a,b,c) VALUES (tab1(ii),tab2(ii),tab3(ii));
    commit;
END;
/
PL/SQL procedure successfully completed.

Elapsed: 00:00:03.15
...
Рейтинг: 0 / 0
Быстрое создание записей в БД
    #37050122
Фотография Apex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglAlexander Ryndin,

Там была опечаточка к коде: numrec number :=100000 1000000;
И Все измерения я проводил в виртуалке. Скорость в ней падает вдвое (минимум).
Причем на обычном ноуте среднего класса, а не продакшн сервере )
Ты прикалываешься? Результаты продакшн-серверов здесь .
...
Рейтинг: 0 / 0
7 сообщений из 57, страница 3 из 3
Форумы / Сравнение СУБД [игнор отключен] [закрыт для гостей] / Быстрое создание записей в БД
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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