powered by simpleCommunicator - 2.0.41     © 2025 Programmizd 02
Форумы / PowerBuilder [игнор отключен] [закрыт для гостей] / Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
22 сообщений из 22, страница 1 из 1
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33814272
Outcast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Программа изначально работала с курсором в основном потоке и запускала сохраненную процедуру (proc1 с параметрами) оракла
производился анализ результата ее выполнения
- в случае успешного завершения - commit;
- в случае неудачи - roolback и запуск процедур (proc2 и proc3 с параметрами ) выполняющие
корректное завершение операции в БД и логирование

В связи с тем, что список записей, формируемых курсором постоянно увеличивается,
а скорость выполнения процедуры proc1 остается достаточно низкой ( от 1 до 30 секунд),
общее время отработки списка становится неприемлемым. Оптимизировать скорость выполнения
процедур путем внедрения исправлений в код - шаг нетривиальный и скорее всего неприемлемый
поскольку сразу теряется тех поддержка разработчиков установленного БД

Для решения данного вопросы было принято решение сделать многопоточный запуск процедуры proc1 и proc2 proc3 соответственно. Для того что бы не перегрузить сервер количество потоков должно быть не более N (в нашем случае 20).

При анализе вопросов на форуме натолкнулся на "вопрос по SharedObject"
( http://www.sql.ru/forum/actualthread.aspx?tid=104627&hl=thread )
представленный потоковый обьект и обьект коммуникации от Филлипа, как мне кажется могут подойти для решения этой задачи. Вопрос в том - как эти кубики сложить в единую схему? Где производить подсчет threads? Как их запускать? Можно ли использовать эти 2 обьекта в глобальной процедуре ( сейчас так и работает - в одном потоке) или необходимо создать nonvisual userobject (обязательно ли это) ?

Не смогли бы уважаемые профессионалы помочь разобраться с этими наболевшими вопросами.
Заранее Вам благодарен.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33814451
Outcast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
(Дополнение)
Чтобы не быть голословным приведу укороченный код процедуры

Dec Oper_id
datetime Oper_date
string Oper_RetCode, Oper_RetMessage, Oper_ErrMessage, Oper_ErrCode, tmp_data, Log_Name

Integer tmp_id,Person_ID, i, j, Ok_Command, Bad_Command
Boolean Is_Error

work_log('Подтверждение в базе данных...')

// процедура proc1
DECLARE Set_WO_ADP PROCEDURE FOR WorkOrders_API.Set_WO_Adopted(:Oper_id, :Oper_date, :Person_ID)
USING sqlca;
// процедура proc2
DECLARE Set_WO_ERR PROCEDURE FOR WorkOrders_API.Set_WO_Error(:Oper_id)
USING sqlca;
// процедура proc3
DECLARE Set_WO_INS PROCEDURE FOR WorkOrders_API.Insert_WO_Error (:Oper_id, 1, :Oper_ErrCode, :Oper_ErrMessage)
USING sqlca;

// Собственно подтверждение

startprogress(UpperBound(List_Order))
for i=1 to UpperBound(List_Order)
progress()
If List_Order .Flag = confirm then
Oper_id = List_Order[Sort_Order].Current_ID
select sysdate into :Oper_date from dual;
Oper_RetCode = ''
Oper_RetMessage = ''
Oper_ErrMessage = ''
Oper_ErrCode = ''
execute set_WO_ADP;
fetch set_WO_ADP into :Oper_RetCode, :Oper_RetMessage;
if Oper_RetCode = '0' then // Усе Ок
commit;
else // были ошибки ПОДТВЕРЖДЕНИЯ
Oper_ErrMessage = Oper_RetMessage
Oper_ErrCode = Oper_RetCode
Rollback;
Execute Set_WO_ERR;
fetch set_WO_ERR into :Oper_ErrCode, :Oper_ErrMessage;
Execute Set_WO_INS;
fetch set_WO_INS into :Oper_ErrCode, :Oper_ErrMessage;
Commit;
Error_Log('Подтверждение в базе данных', 0)
end if
end if
next

stopprogress()

return
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33815290
Фотография Филипп
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OutcastПрограмма изначально работала с курсором в основном потоке и запускала сохраненную процедуру (proc1 с параметрами) оракла
производился анализ результата ее выполнения
- в случае успешного завершения - commit;
- в случае неудачи - roolback и запуск процедур (proc2 и proc3 с параметрами ) выполняющие корректное завершение операции в БД и логирование
Каким образом выше выделенное может быть решено многопоточным запуском процедуры proc1 и proc2 proc3 соответственно?
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33815385
Фотография Dmitry.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ФилиппКаким образом выше выделенное может быть решено многопоточным запуском процедуры proc1 и proc2 proc3 соответственно?
Вместо запуска этого алгоритма 20 раз последовательно, хотят запускать его 20 раз но паралельно. т.е. снизить общее время выполнения в разы.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33815422
Фотография Филипп
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitry. ФилиппКаким образом выше выделенное может быть решено многопоточным запуском процедуры proc1 и proc2 proc3 соответственно?
Вместо запуска этого алгоритма 20 раз последовательно, хотят запускать его 20 раз но паралельно. т.е. снизить общее время выполнения в разы.
Хорошо если так. Я лично это прочитал так, что хотят proc1 в отдельный поток, proc2 в отдельный и proc3 в отдельный...
Каков вопрос, таков и вопрос :-)
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33815465
Фотография Dmitry.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да это можно реализовать.

надо создать :

невизуальный обьект для слушания
Код: plaintext
n_thread_locator.of_exec_end(int ret_code)

невидимый обьект с ф-цией со всеми нужными параметрами
Код: plaintext
n_thread.of_exec(n_thread_locator locator, Oper_id, Oper_date, Person_ID, Oper_ErrCode, Oper_ErrMessage)
эта ф-я после выполнения кода (вызова процедур) должна вызвать
Код: plaintext
locator.of_exec_end(ret_code)

--
далее код типа:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
//on create: create  20  shared objects
for i= 1  to  20 
   sharedobjectregister("n_thread", "thread_"+string(i))
next

//execute  20  threads:
n_thread thread
for i= 1  to  20 
   sharedobjectget( "thread_"+string(i) , thread)
   thread.post of_exec(locator, ...)
next

//on destroy: destroy shared objects
for i= 1  to  20 
   sharedobjectunregister( "thread_"+string(i) )
next

причем все это может быть в локаторе. и локатор-же может менеджить (считать, запускать, слушать) потоки
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817060
Estets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dmitry. ФилиппКаким образом выше выделенное может быть решено многопоточным запуском процедуры proc1 и proc2 proc3 соответственно?
Вместо запуска этого алгоритма 20 раз последовательно, хотят запускать его 20 раз но паралельно. т.е. снизить общее время выполнения в разы.
Правда с таким же успехом можно получить и замедление в несколько раз :-(

Лучше для начала провести эсперимент...

OutcastОптимизировать... процедур путем внедрения исправлений в код - шаг нетривиальный и скорее всего неприемлемый
поскольку сразу теряется тех поддержка разработчиков установленного БД
Весьма странный подход, когда для ускорения работы серверной компоненты, правится клиентская часть.

Чем и хорош SQL сервер, что в нем не обязательно исправлять исходные процедуры, можно написать свои паралельные, оптимизированные. Дописывание надеюсь не приводит к "потере поддержки"?

Как вариант таки заставить разработчиков оптимизировать это хозяйство, если нет править самому, нахрен такая поддержка нужна.

Ну и последнее я не специалист по ORACLE, но судя по опыту в SQL, практически все что делается курсором можно сделать проще, быстрее и надежнее, без курсора. Обрабатывая записи пакетом и соответственно избавившись от линейной зависимости времени от количества записей.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817303
Фотография PL99
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то, Estets все слова сказал уже :-)
Но тут вот у меня пара замечаний относительно кода клиентского
1. Не самый лучший способ определения границы цикла, Outcast
Код: plaintext
for i= 1  to UpperBound(List_Order)
хотя, конечно, это копейки, но, как-то... неаккуратно

2.при отработке пакета в цикле действительно принципиально передавать в процедуру точное время вызова для каждого элемента массива?

Outcast
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
// Собственно подтверждение

startprogress(UpperBound(List_Order))
   for i= 1  to UpperBound(List_Order)
      progress()
      If List_Order[i].Flag = confirm then
         Oper_id = List_Order[Sort_Order[i]].Current_ID
         select sysdate into :Oper_date from dual;
         Oper_RetCode = '' 
         Oper_RetMessage = ''
         Oper_ErrMessage = ''
         Oper_ErrCode = ''
         execute set_WO_ADP;
         fetch set_WO_ADP into :Oper_RetCode, :Oper_RetMessage;
         if Oper_RetCode = '0' then   	//  Усе Ок
	commit;
         else			// были ошибки ПОДТВЕРЖДЕНИЯ
...
         end if
      end if
   next
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817384
Outcast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To PL99

При отработке каждого запроса действительно необходимо
точное время подтверждения запроса. И время именно с сервера.

UpperBounds же использовал для определения размера динамического массива
ListOrder, который в свою очередь собирался из курсора. При каждом запуске количество записей в массиве различно (от 1 до 5000 прибл.).

To Dmitry
Да, Вы правы, мы действительно хотим в разы повысить производительность
подтверждений запросов путем распараллеливания запуска процедуры proc1
Правда Ваш код в этом случае будет отрабатывать N (=20) запросов за время, равное самому длительному подтверждению из N. Это возможно волне приемлемое решение. Спасибо.

Для ускорения предложенного решение есть идея подтверждения производить поточно и по мере отработки каждого потока подзагружать свежими данными.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817447
Estets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OutcastПравда Ваш код в этом случае будет отрабатывать N (=20) запросов за время, равное самому длительному подтверждению из N. Это возможно волне приемлемое решение. Спасибо.

Именно тут на мой взгляд и кроется ошибка, код будет отрабатывать, точно дольше чем "время, равное самому длительному подтверждению из N", возможно за время "сумма всех времен выполнения 1..N", может меньше, может больше, это уже зависит от количества процессоров на сервере, настроек самого сервера и много чего еще.

И не стоит забывать о такой проблеме ORACLE как возможный Rollback в одном из потоков, на сколько вырастет сегмент отката (если не ошибаюсь) при выполнении не одной а 20 процедур.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817458
Outcast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To Estets

Не знаю, что сказать Вам на этот счет ))) (Подробности же Вас не интересуют, не правда ли? )

Меня же интересует "принципиальная схема механизма параллельного
запуска хранимых процедур" на клиенте.

Линейного возрастания скорости я не жду - это и ежу понятно, но качественного ускорения добиться этим можно.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817475
Фотография PL99
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OutcastTo PL99

При отработке каждого запроса действительно необходимо
точное время подтверждения запроса. И время именно с сервера.

UpperBounds же использовал для определения размера динамического массива
ListOrder, который в свою очередь собирался из курсора. При каждом запуске количество записей в массиве различно (от 1 до 5000 прибл.). Гм...
Я имел ввиду то, что количество записей в массиве следует определять не во время , а до цикла. Тоже самое относилось и к дате, передаваемой в процедуру.
Ну, и уж до кучи, а почему Вы не проверяете успешность вызова процедур?
Код: plaintext
1.
if sqlca.sqlcode <  0  then
...
PowerBuilder Help Error handling It is good practice to test the success/failure code after executing an EXECUTE statement.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817503
Outcast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To PL99

процедура определения верхней границы отрабатывает единожды как раз до цикла, далее значение сохраняется уже в коде цикла. Конечно можно это было сделать и через переменную.

А вот время - длительность подтверждения варьируется (от секунды и более)
В этом случае значение времени будет не совпадать с истинным.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817553
Фотография PL99
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Outcastпроцедура определения верхней границы отрабатывает единожды как раз до цикла, далее значение сохраняется уже в коде цикла. Конечно можно это было сделать и через переменную.Граница цикла For в случае вызова через UpperBound определяется для каждой итерации, поэтому сделать через переменную было бы аккуратнее.

OutcastА вот время - длительность подтверждения варьируется (от секунды и более)
В этом случае значение времени будет не совпадать с истинным.Понятно, это сомнений не вызывает. Но вот физический смысл подобного действия... У вас процесс подтверждения документов инициирован пользователем (я такой вывод сделал на основании того, что вы выводите progresbar). Не логичнее ли считать, что все документы, подтвержденные в результате этого процесса, обработаны в одно и тоже время?
Впрочем, не смею настаивать на этой точке зрения, т.к. бизнес-процесс мы здесь не обсуждаем.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817576
Estets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OutcastНе знаю, что сказать Вам на этот счет ))) (Подробности же Вас не интересуют, не правда ли? )

Если бы не интересовало, то я бы не встревал в разговор.
Outcast
Меня же интересует "принципиальная схема механизма параллельного
запуска хранимых процедур" на клиенте.

Линейного возрастания скорости я не жду - это и ежу понятно, но качественного ускорения добиться этим можно.
У меня была практически аналогичная задача, по проведению документов и решалась примерно так же, DW со списком идентификаторов, и бегущий курсорчик вызывающий ХП с нужным идентификатором и отмечающий в списке галочку/крестик по итогам выполнения процедуры. 100 документов - 200 секунд.

Была поставлена задача повести 10 000 документов за 2 000 секунд АКА пол часа. Вообщем задача была решена, но решена именно:

1) Оптимизацией самой ХП, оптимизацией логики, выкидыванием ненужных проверок, укорением нужных проверок и т.п.
2) Переносом всей обработки на сервер, т.е. на сервере в ХП формируется временная таблица с нужными данными и исползуется уже серверный курсор для вызова ХП-проведения. Этим мы убираем потери на сеть и вызов ХП с клиента.

Все это дало ускорение в 15 раз, правда никаких красивостей на клиенте не отображалось типа галочек и прогресс-баров. Это один из вариантов решения
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817620
Estets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
P.S. Запусть паралельно еще один поток мне даже не пришло в голову, потому что есть у меня подозрение что если это и даст ускорение, то 20-30% а это меня не устраивало.

P.P.S Если бы мне надо было ускорить выполнение на 2 порядка, то я бы смотрел именно на пакетную обработку, хотя в процедуре проведения сложная логика создания проводок, около 15 insert-ов и select-ов вообще более 30, но только пакетная обработка возможно позволила бы решить такую задачу.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817665
Outcast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To Estets

Вы затронули интересную сторону оптимизации. Не могли бы Вы поподробнее с нею ознакомить (пакетная обработка).
Просто в своей программе мы используем АПИ разработчика БД (около 800 таблиц - биллинг)
Возможно ли в пакетной обработке использовать эти же процедуры АПИ?
Самим же писать низкоуровневую логику обработки запросов...
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33817701
Outcast
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
TO PL99

Своими замечаниями (на счет времени) Вы мне подсказали альтернативный метод подсчета - вначале в переменную сохраняется время сервера, а после этого только к нему добавляется дельта предыдущего времени отработки - таким образом точность - в допустимых пределах и лишних обращений нет. Спасибо.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33818782
Estets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OutcastTo Estets

Вы затронули интересную сторону оптимизации. Не могли бы Вы поподробнее с нею ознакомить (пакетная обработка).
Просто в своей программе мы используем АПИ разработчика БД (около 800 таблиц - биллинг)
Возможно ли в пакетной обработке использовать эти же процедуры АПИ?
Самим же писать низкоуровневую логику обработки запросов...

Если использовать АПИ разработчика, то на мой взгляд проще всего перенести курсор в сервер, на этом можно достаточно сильно оптимизировать время выполнения.

Все остальное уже требует влезание в код разработчика, или написание паралельного кода.Например у нас в процедуре проведения документа проверялся пользователь и его права на выполнение данной операции, хоть это занимало и мало времени, но если умножить время на 10 000 операций то получалось огого. Соответственно проверку прав пользователя вынесли в процедуру с курсором, которая выполняется один раз и вызывает в цикле процедуры проведения уже без проверки.

А вот массовая обработка требует именно "Самим же писать низкоуровневую логику", на свой страх и риск. Например есть процедура которая записывает запись в лог и вызывается для каждого документа.
Если она отрабатывает 0.1 сек то 10 000 * 0.1 = 1.5 мин. А если заменить ее на
Код: plaintext
1.
2.
INSERT INTO t_log(doc_id, date ,,,)
SELECT #list_of_doc.id, getdate(),,,,
FROM #list_of_doc...
То независимо от кодичества документов 1 или 100 000 выполнятся это будет примерно 1 сек.

Если требуется расчеты то ожно почитать советы ASCRUS в "Проектировании БД" о предварительных расчетах агрегатных сумм именно для разрыва линейной зависимости времени расчетов от количества документов.

Но все это достаточно спецефично, и дать общий совет не зная вашей задачи вряд ли у кого получится.
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33821073
Фотография Dmitry.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а мне интересно что получится с потоками.
..хотя и решение с массовой обработкой значительно лучше
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33822712
Фотография Dmitry.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот пару классов по theads
...
Рейтинг: 0 / 0
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
    #33833884
Estets
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Outcast:

Как результаты тестирования?
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / PowerBuilder [игнор отключен] [закрыт для гостей] / Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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