![]() |
#1 |
Участник
|
![]()
удаляли сегодня инвентаризационный журнал,я громко матюкался когда обнаружил этот тупняк (88000 строк журнала удалялось 4 часа).
итак таблица: InventJournalTrans X++: void delete() { ; ttsbegin; appl.inventUpdateTTSControl().setTTSBeginLock(); super(); if (this.journalType == InventJournalType::Count) InventItemLocation::updateStopCountingJournal(this); InventUpd_DeleteMovement::newMovement(InventMovement::construct(this)).updateNow(); if (this.voucher) { if (this.numOfVoucherLines() == 0) // нас интересует эта строка !!! JournalError::deleteVoucher(tableNum(InventJournalTable),this.journalId,this.voucher); } appl.inventUpdateTTSControl().setTTSCommitLock(); ttscommit; } X++: Integer numOfVoucherLines() { return (select forceplaceholders count(recId) from inventJournalTrans index hint VoucherIdx where inventJournalTrans.journalId == this.journalId && inventJournalTrans.voucher == this.voucher).recId; } ![]() X++: // SHiSHok 20070331 boolean voucherLineExist() { return (select firstfast firstonly forceplaceholders recId from inventJournalTrans index hint VoucherIdx where inventJournalTrans.journalId == this.journalId && inventJournalTrans.voucher == this.voucher).recId != 0; } void delete() { ; ttsbegin; appl.inventUpdateTTSControl().setTTSBeginLock(); super(); if (this.journalType == InventJournalType::Count) InventItemLocation::updateStopCountingJournal(this); InventUpd_DeleteMovement::newMovement(InventMovement::construct(this)).updateNow(); if (this.voucher) { // if (this.numOfVoucherLines() == 0) // if (!this.voucherLineExist()) JournalError::deleteVoucher(tableNum(InventJournalTable),this.journalId,this.voucher); } appl.inventUpdateTTSControl().setTTSCommitLock(); ttscommit; }
__________________
--- SHiSHok |
|
|
За это сообщение автора поблагодарили: mazzy (5), belugin (6), kashperuk (3), konopello (2), fialka (1), bobski (1). |
![]() |
#2 |
Участник
|
ну, собственно, в 4-й версии таким широким жестом проверяется наличие строк для удаления (метод Delete()) в следующих таблицах:
InventJournalTrans ProdJournalBOM ProdJournalProd ProdJournalRoute ProjJournalTrans TutorialJournalTrans (sic! чему нас учат!) более нигде этот волшебный метод numOfVoucherLines не вызывается.
__________________
Felix nihil admirari |
|
![]() |
#3 |
Участник
|
Хоть и было, это давно, но все же спрошу, а действительно ли прирост был в 6 раз, ну или хотя бы в 2 или 3 раза ?
Действительно, подсчет строк не самый, наверное, лучший вариант для определения, есть ли записи в таблице или нет, но замечу, что во всех таблицах, на которых есть этот волшебный метод, присутствует индекс VoucherIdx, в состав, которого входят оба поля, так что подсчет количества строк должен быть сравним с поиском первой записи по времени, по крайней мере для повторных запросов. Да, на тестовой выдало время 35 мин, а дальше, что ? Думаю, если подождать эти 35 минут, то Progress Bar будет показывать уже совсем другое время ![]() На мой взгляд, проблема того, что строки удаляются долго, в том, что все они удаляются в одной транзакции. Безусловно, при проверке на существование одной записи прирост производительности операции удаления будет, но не в разы.
__________________
Sergey Nefedov |
|
![]() |
#4 |
Moderator
|
Стоит помнить, что для складских журналов можно настроить режим, при котором один ваучер выделяется не на строку, а на все строки с одинаковой датой . Для этого случая - гипотеза о сопоставимости времени выполнения count() и загрузки одной строки не срабатывает...
Да и в режиме Номенклатура+дата, выделение нового ваучера происходит только если в очередной строке номенклатура отличается от номенклатуры в предыдущей строке. Если у тебя, скажем, списывается много одинаковой номенклатуры с разными серийными номерами - гипотеза тоже не срабатывает. |
|
![]() |
#5 |
Участник
|
да, мне тоже показался прирост совсем незначительным. на 2500 записях я никакого прироста не ощутил. но методы поправил.
кстати, вопрос методологический: а зачем вообще удалять строки из инв. журнала?
__________________
Felix nihil admirari |
|
![]() |
#6 |
Участник
|
Как раз наоборот. Много мелких транзакций в цикле выполняются заметно дольше, чем одна общая транзакция на весь цикл. Время тратится на отдельное открытие-закрытие каждой мелкой транзакции.
|
|
![]() |
#7 |
Administrator
|
... но при этом на больших объемах данных и при многопользовательской работе это ставит БД колом на время выполнения транзакции. Хотя формально получается быстрее (аналогично тому, что цикл с прогресс-баром крутится медленнее, чем без него, но при этом психологически кажется что быстрее)
__________________
Возможно сделать все. Вопрос времени |
|
![]() |
#8 |
Участник
|
А смысл разносить фактическое нувое количество если по системе также 0?
|
|
![]() |
#9 |
Участник
|
а поразвёртнутей можно? я не компетентен в вопросе настолько, чтоб из вопроса на вопрос составить себе ответ.
__________________
Felix nihil admirari |
|
![]() |
#10 |
Участник
|
Цитата:
Также могут начать возникать блокировки чтения (правда зависит от версии системы и уровня изоляции при чтении - READ_COMMITTED_SNAPSHOT в SQL 2005 говорят проблему эту решает) И если транзакция будет длится, скажем, 4 часа, но через 3:59 выключат свет в серверной ![]() Поэтому время на открытия/закрытия мелких транзакций выгоднее с точки зрения скорости. Но целостность данных дороже. |
|
![]() |
#11 |
Участник
|
Цитата:
Такие строки и удаляются |
|
![]() |
#12 |
Участник
|
Цитата:
Сообщение от SRF
![]() Хоть и было, это давно, но все же спрошу, а действительно ли прирост был в 6 раз, ну или хотя бы в 2 или 3 раза ?
Действительно, подсчет строк не самый, наверное, лучший вариант для определения, есть ли записи в таблице или нет, но замечу, что во всех таблицах, на которых есть этот волшебный метод, присутствует индекс VoucherIdx, в состав, которого входят оба поля, так что подсчет количества строк должен быть сравним с поиском первой записи по времени, по крайней мере для повторных запросов. Цитата:
Сообщение от fed
![]() Стоит помнить, что для складских журналов можно настроить режим, при котором один ваучер выделяется не на строку, а на все строки с одинаковой датой . Для этого случая - гипотеза о сопоставимости времени выполнения count() и загрузки одной строки не срабатывает...
Да и в режиме Номенклатура+дата, выделение нового ваучера происходит только если в очередной строке номенклатура отличается от номенклатуры в предыдущей строке. Если у тебя, скажем, списывается много одинаковой номенклатуры с разными серийными номерами - гипотеза тоже не срабатывает. И для выбора одной строки скорее всего будет использоваться кэш, поэтому сильно снижается время на выборку. Только что знакомый мой попробовал симулировать данную ситуацию, создав табличку, соответствующий индекс, т.д. Кол-во записей - 100 тысяч. Для выбора одной записи потребовалось: CPU time: 0 ms, Elapsed time: 0 ms Для выполнения подсчета записей потребовалось: CPU time: 16 ms, Elapsed time: 100 ms Результат, соответственно, таков, что время выбора одной записи лучше в 100 раз (на самом деле, в бесконечность, но кто считает ![]() P.S. Расчет был с использованием индекса по integer полю. Для индекса по нескольким полям, тем более строковым, разница будет еще больше. |
|
![]() |
#13 |
Участник
|
практически я уже переписал методы на всех этих таблицах, как учили в школе.
интересно, много ли ещё таких мест к оптимизации? можно их как-то все автоматически найти?
__________________
Felix nihil admirari |
|
![]() |
#14 |
Участник
|
Совершенно верно, именно это я и собирался сказать.
|
|
Теги |
inventjournal, оптимизация, производительность, запрос (query) |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|