Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M Новый топик    Ответить
 Загрузка данных из MSSQL в Cache  [new]
DirksDR
Member

Откуда: Пермь
Сообщений: 340
День добрый!

Упражняюсь с загрузкой с сервера АСУТП в Cache данных.
Добился скорости около 4 тыс. записей в секунду.
Индексов нет, глобаль получается в виде:
^User.Tel4ValuesD("07064BOV7K8D2EW60KBYWY","20151005:222233",109.11447906494099,0) = $lb("","","","","20151005:223041","")
Журналирование отключено, компьютер офисный, Cache evaluation

Cache for Windows (x86-32) 2015.2.1 (Build 705U_SU) Tue Sep 1 2015 09:44:03 EDT

Все ли я правильно делаю? Есть ли резервы по повышению быстродействия?
+ Ниже привожу текст программы
#include %occInclude
   
Tel4LoadTir  
  
  
Set conn=##class(%SQLGatewayConnection).%New()
  
Set sc=conn.Connect("Tel4Kky","ois","ois",0) 
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
    
  w 
!,$zts," sql"
  
set t1=$zts
  set 
recCount=0

  
Set res=##class(%ResultSet).%New("%DynamicQueryGW:SQLGW")
  
Set sc=res.Prepare("select * from  tel4.dbo.SERVER_ARCHIVE_FLOAT where ABSOLUTE_NUMBER > '15004Y6SGV6C1NGMRUG9N6' and ABSOLUTE_NUMBER<='71003PGMJ8LX1AGUDEAJ8D' ",,conn)
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit
    

  Set 
sc=res.Execute()
  
If $$$ISERR(scdo $System.Status.DisplayError(scquit

  set 
rc=$SORTBEGIN(^User.Tel4ValuesD)
  
!,"rc=",rc

  
While res.Next() 
  
{     
    
merge flds=res.Data
    
;zwrite flds

    
set absnum=flds("ABSOLUTE_NUMBER";;="07064BOV7K8D2EW60KBYWY"
    
set cc=flds("CONFIRM_CODE";;=""
    
set cdt=flds("CONFIRM_DATETIME";;=""
    
set cu=flds("CONFIRM_USER_ID")  ;;=""
    
set VALUE=flds("DATA")  ;;=78.689926147460895
    
set ddt=$translate(flds("DISPATCH_DATETIME"),"-:","")  ;;="2015-11-02 10:35:25.113"
    
set ddt=$translate(ddt," ",":")
    
set ddt=$e(ddt,1,15)
    
set edt=$translate(flds("EVENT_DATETIME"),"-:","")  ;;="2015-11-02 10:35:25.113"
    
set edt=$translate(edt," ",":")
    
set edt=$e(edt,1,15)
    
set stat=flds("STATUS")  ;;=0
    
set valid=flds("VALID")  ;;=""      

    
&sql(  INSERT  into SQLUser.Tel4Values (ABSOLUTE_NUMBER,EVENT_DATETIME,DISPATCH_DATETIME,DATA,STATUS,VALID,CONFIRM_DATETIME,CONFIRM_USER_ID,CONFIRM_CODE)
    
VALUES :absnum:edt:ddt:VALUE:stat:valid:cdt:cu:cc))  

    
IF SQLCODE'=0  {
      
WRITE !,"SQLCODE=",SQLCODE," -- ",$SYSTEM.SQL.SQLCODE(SQLCODE)
    
}
       
    
set recCount=recCount+1
  

    
  
Set rc $SortEnd(^User.Tel4ValuesD)
  
!,"rc=",rc
  
  
set t2=$zts
  w 
!,recCount," записей"
  
!,$p(t2,",",2)-$p(t1,",",2)," сек"

  
Set sc=conn.%Close()
  
Quit
5 апр 16, 17:20    [19020026]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
DAiMor
Member

Откуда: Volzhsky -> Moscow -> CZ, Brno
Сообщений: 2583
DirksDR,

Ну если хочется экстрима, то можно отключить журналирование, и/или писать напрямую в глобалы без SQL или объектов.

А так в Caché полно возможностей, чтобы увидеть слабые места, какая строчка медленней всего, и зная это можно пробовать ее оптимизировать.
Если процессор не загружен на 100% и диск не упирается в очередь, значит запас у системы еще есть, и возможно есть что оптимизировать. хотя 100% CPU это еще не показатель что все далается правильно
5 апр 16, 17:44    [19020128]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
eduard93
Member

Откуда:
Сообщений: 161
DirksDR,

select * замените на список только необходимых полей.
5 апр 16, 21:05    [19020764]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
doublefint
Member

Откуда: Беларусь, Минск
Сообщений: 931
DirksDR,
Посмотрите материалы Школ - почти каждый год рассматривается тема оптимизации производительности.
Например,
%Persistent:%SortBegin()
%Persistent:%SortEnd()
5 апр 16, 21:36    [19020856]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
Alexey Maslov
Member

Откуда: СПб
Сообщений: 1526
DirksDR,

Ваша тестовая среда тормозит архитектурно, как любая x86-32 система. Ограничения на размер кэша добавляет и пробная версия. Сейчас вы скорее всего упираетесь в диск. С бОльшим кэшем (не менее 1 GB на вскидку) вы сможете позволить себе больше, пути для улучшения алгоритма есть.

Если не требуется мгновенная доступность данных, я бы упростил структуру хранения до стандартной и лучше завел бы дополнительные sql-индексы, кои достраивал бы в фоне, отдельными процессами. На (хотя бы) двухядерном компе будет работать быстрее, чем когда все делается в одном процессе, как у вас сейчас.

А м.б. тормозит не запись в Cache, a чтение из sql, проверяли?
5 апр 16, 22:27    [19020998]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3116
Блог
DirksDR
Добился скорости около 4 тыс. записей в секунду.
Мало.
Проверьте скорость чтения вне Caché и в своём коде (закомментируйте $sort*/insert и оставьте только merge), чтобы узнать её потолок. Только тогда можно начать думать об оптимизации записи в Caché.

У меня по сети данные из 19 полей разного типа в DbVisualizer возвращаются со скоростью ~47000 (зап./сек.)
DirksDR
Все ли я правильно делаю?
  • скорость выполнения замерять лучше "традиционно":
    set t1=$zh
    ; здесь некий код
    write $zh-t1" сек"
  • параметры в запрос лучше передавать именно как параметры, а не зашивать их в сам текст:
    do res.Prepare("select * from  tel4.dbo.SERVER_ARCHIVE_FLOAT where ABSOLUTE_NUMBER > ? and ABSOLUTE_NUMBER<=? ",,conn)
    do res.Execute("15004Y6SGV6C1NGMRUG9N6","71003PGMJ8LX1AGUDEAJ8D")
    Безопасники потом скажут Вам спасибо.
  • в конце хорошо бы правильно подчищать за собой:
    do res.Close()
    do conn.Disconnect()
  • пользуйтесь try/catch и соответствующими макросами ($$$ThrowOnError). Код станет лаконичнее и проще. Примеры можете найти здесь же.
DirksDR
Есть ли резервы по повышению быстродействия?
Есть резервы по кардинальному упрощению кода, вернее по сведению его к одному простому запросу вида:
insert into caché(field1,field2,fieldNselect $TRANSLATE(field1,'-:',''),$EXTRACT(field2,1,15),fieldN from (select field1,field2,fieldN from mssql where ABSOLUTE_NUMBER BETWEEN and ?)
, используя линковочную таблицу.
6 апр 16, 09:06    [19021725]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
DirksDR
Member

Откуда: Пермь
Сообщений: 340
Спасибо за отклики.

servit, Alexey Maslov
Вы опять оказались правы. Больше 80% времени занимает чтение данных с сервера MSSQL.
Наверное, это простительно, т.к. до него больше 100км.
Диск бОльшую часть времени отдыхал, я думаю, что за счет использования $SORTBEGIN/$SortEnd.
Любопытно было наблютать в Task Managere, как увеличивается память занятая процессом.
Видимо, предварительная сортировка выполняется в памяти процесса, я думал, что в кеше базы данных.
Процессор был занят на 15-22%.
А это значит, что есть резервы по скорости загрузки!

Линкованные таблицы я использовал. Но "insert .... select ...." сделать не получилось.
+ Выдается ошибка компиляции:
Компиляция началась в 04/06/2016 14:17:29 с квалификаторами 'cukb /checkuptodate=expandedonly'
Компиляция программы: : Tel4loadDic.MAC
Cache ObjectScript Error while compiling SQL statement: <UNDEFINED>parseSelect+4^%qaqcmx *mt("o",2)
ERROR: Tel4loadDic.MAC(223) : <UNDEFINED>parseSelect+4^%qaqcmx *mt("o",2) :
Обнаружено 1 ошибок во время компиляции.
+ Текст подпрограммы, вызвавший ошибку:
TestInsSel  

  
WRITE !,"Populating table with data"
  
NEW SQLCODE,%ROWCOUNT,%ROWID
  
&sql(INSERT INTO SQLUser.DESC_HW_DICTIONARY (OBJECT_NUMBER,TREE_LEVEL,PARENT_OBJECT_NUMBER,OBJECT_TYPE,OBJECT_NAME
  
,LINK,VISIBLE,IS_OBJECT,IS_ACTIVE,ADD_TO_DESCRIPTION,DATA_LIVE_PERIOD,MODULE_ID,CAN_BE_DELETED,MEASURE_UNITS)
   
SELECT OBJECT_NUMBER,TREE_LEVEL,PARENT_OBJECT_NUMBER,OBJECT_TYPE,OBJECT_NAME
   
,LINK,VISIBLE,IS_OBJECT,IS_ACTIVE,ADD_TO_DESCRIPTION,DATA_LIVE_PERIOD,MODULE_ID,CAN_BE_DELETED,MEASURE_UNITS
  
FROM dbo.DESC_HW_DICTIONARY)
  
  
IF SQLCODE=0 {
    
WRITE !,"Number of records inserted=",%ROWCOUNT
    
WRITE !,"Row ID of last record inserted=",%ROWID }
  
ELSE {
    
WRITE !,"Insert failed, SQLCODE=",SQLCODE }

 
quit
+ В то же время курсор отработал без ошибки:
Tel4loadDic  ;=========================================== 0.05cek
 ;;New mpid, oname, mname, longCode, otype, cex, dns, bul, Dat, v, rec, tab, mask ;Clock
 
 
&sql( 
   
DECLARE c5 CURSOR FOR 
   
SELECT OBJECT_NUMBER,TREE_LEVEL,PARENT_OBJECT_NUMBER,OBJECT_TYPE,OBJECT_NAME
   
,LINK,VISIBLE,IS_OBJECT,IS_ACTIVE,ADD_TO_DESCRIPTION,DATA_LIVE_PERIOD,MODULE_ID,CAN_BE_DELETED,MEASURE_UNITS
  
FROM dbo.DESC_HW_DICTIONARY
 
)

 
!,$zts," sql"

 
&sql( OPEN c5 )
 
 
!,$zts," open"
 
  
For {
     &sql( 
FETCH c5 INTO :on:tl:pon:ot:oname:link:vi:io:ia:atd:dlp:mid:cbd:mu
     
Q:SQLCODE'=0 
     
     
&sql(  INSERT  into SQLUser.DESC_HW_DICTIONARY 
       
(OBJECT_NUMBER,TREE_LEVEL,PARENT_OBJECT_NUMBER,OBJECT_TYPE,OBJECT_NAME,
         
LINK,VISIBLE,IS_OBJECT,IS_ACTIVE,ADD_TO_DESCRIPTION,DATA_LIVE_PERIOD,MODULE_ID,CAN_BE_DELETED,MEASURE_UNITS)
      
VALUES :on:tl:pon:ot:oname:link:vi:io:ia:atd:dlp:mid:cbd:mu)  
      
)
     
      
!
    
}
 &sql( 
CLOSE c5 )
 
!,$zts," close"
 
Q
Дает ли преимущества использование JDBC подключения? Я использовал ODBC...
6 апр 16, 12:51    [19022800]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3116
Блог
DirksDR,

Или можно воспользоваться новой фичей Caché Monitor: Query Cloud (есть два видео с демонстрацией)
6 апр 16, 13:03    [19022902]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
DAiMor
Member

Откуда: Volzhsky -> Moscow -> CZ, Brno
Сообщений: 2583
DirksDR
Дает ли преимущества использование JDBC подключения? Я использовал ODBC...

Разумеется есть преимущества. JDBC сам по себе медленней из-за Java.
вот можно глянуть подробнее
6 апр 16, 13:09    [19022942]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка данных из MSSQL в Cache  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3116
Блог
DirksDR
Линкованные таблицы я использовал. Но "insert .... select ...." сделать не получилось.
Потому что есть ограничения, которые упомянуты в самом первом примечании.

"AS IS" запрос применить не получится, но кардинально упростить код, сведя его к этому запросу, можно, разбив запрос на два этапа (что Вы и сделали):
  set a="15004Y6SGV6C1NGMRUG9N6"b="71003PGMJ8LX1AGUDEAJ8D"
  
&sql(declare cMSSQL cursor for select f1,f2 from tel4.dbo."SERVER_ARCHIVE_FLOAT" where f3>:a and f3<=:b FOR READ ONLY)
  &sql(
open cMSSQL)
  
for  {
    &sql(
fetch cMSSQL into :f1,:f2)
    
quit:SQLCODE

    
&sql(INSERT into SQLUser.Tel4Values(f1,f2VALUES ($TRANSLATE(:f1,'-:',''),$EXTRACT(:f2,1,15)))
  }
  &sql(
close cMSSQL)
6 апр 16, 13:37    [19023103]     Ответить | Цитировать Сообщить модератору
Все форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M Ответить