Гость
Форумы / PowerBuilder [игнор отключен] [закрыт для гостей] / Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i) / 22 сообщений из 22, страница 1 из 1
26.06.2006, 12:26
    #33814272
Outcast
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
Программа изначально работала с курсором в основном потоке и запускала сохраненную процедуру (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
26.06.2006, 13:22
    #33814451
Outcast
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
(Дополнение)
Чтобы не быть голословным приведу укороченный код процедуры

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

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

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

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

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

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

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

Ну и последнее я не специалист по ORACLE, но судя по опыту в SQL, практически все что делается курсором можно сделать проще, быстрее и надежнее, без курсора. Обрабатывая записи пакетом и соответственно избавившись от линейной зависимости времени от количества записей.
...
Рейтинг: 0 / 0
27.06.2006, 16:16
    #33817303
PL99
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
Вообще-то, 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
27.06.2006, 16:34
    #33817384
Outcast
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
To PL99

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

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

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

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

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

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

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

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

Линейного возрастания скорости я не жду - это и ежу понятно, но качественного ускорения добиться этим можно.
...
Рейтинг: 0 / 0
27.06.2006, 17:03
    #33817475
PL99
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
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
27.06.2006, 17:13
    #33817503
Outcast
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
To PL99

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

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

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

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

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

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

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

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

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

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

Своими замечаниями (на счет времени) Вы мне подсказали альтернативный метод подсчета - вначале в переменную сохраняется время сервера, а после этого только к нему добавляется дельта предыдущего времени отработки - таким образом точность - в допустимых пределах и лишних обращений нет. Спасибо.
...
Рейтинг: 0 / 0
28.06.2006, 11:42
    #33818782
Estets
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
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
29.06.2006, 10:56
    #33821073
Dmitry.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
а мне интересно что получится с потоками.
..хотя и решение с массовой обработкой значительно лучше
...
Рейтинг: 0 / 0
29.06.2006, 19:45
    #33822712
Dmitry.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
вот пару классов по theads
...
Рейтинг: 0 / 0
05.07.2006, 18:27
    #33833884
Estets
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с сохраненными процедурами в thread (PB 6.5, Oracle 8i)
2 Outcast:

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


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