31.03.2007, 15:17 | #1 |
Участник
|
тупость при удалении из InventJournalTrans
удаляли сегодня инвентаризационный журнал,я громко матюкался когда обнаружил этот тупняк (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). |
10.02.2010, 18:24 | #2 |
Участник
|
ну, собственно, в 4-й версии таким широким жестом проверяется наличие строк для удаления (метод Delete()) в следующих таблицах:
InventJournalTrans ProdJournalBOM ProdJournalProd ProdJournalRoute ProjJournalTrans TutorialJournalTrans (sic! чему нас учат!) более нигде этот волшебный метод numOfVoucherLines не вызывается.
__________________
Felix nihil admirari |
|
10.02.2010, 18:56 | #3 |
Участник
|
Хоть и было, это давно, но все же спрошу, а действительно ли прирост был в 6 раз, ну или хотя бы в 2 или 3 раза ?
Действительно, подсчет строк не самый, наверное, лучший вариант для определения, есть ли записи в таблице или нет, но замечу, что во всех таблицах, на которых есть этот волшебный метод, присутствует индекс VoucherIdx, в состав, которого входят оба поля, так что подсчет количества строк должен быть сравним с поиском первой записи по времени, по крайней мере для повторных запросов. Да, на тестовой выдало время 35 мин, а дальше, что ? Думаю, если подождать эти 35 минут, то Progress Bar будет показывать уже совсем другое время (проверял, будет показывать другие числа, на DAX 4.0 (виртуальная машина от MS) ). На мой взгляд, проблема того, что строки удаляются долго, в том, что все они удаляются в одной транзакции. Безусловно, при проверке на существование одной записи прирост производительности операции удаления будет, но не в разы.
__________________
Sergey Nefedov |
|
10.02.2010, 19:05 | #4 |
Moderator
|
Стоит помнить, что для складских журналов можно настроить режим, при котором один ваучер выделяется не на строку, а на все строки с одинаковой датой . Для этого случая - гипотеза о сопоставимости времени выполнения count() и загрузки одной строки не срабатывает...
Да и в режиме Номенклатура+дата, выделение нового ваучера происходит только если в очередной строке номенклатура отличается от номенклатуры в предыдущей строке. Если у тебя, скажем, списывается много одинаковой номенклатуры с разными серийными номерами - гипотеза тоже не срабатывает. |
|
10.02.2010, 19:06 | #5 |
Участник
|
да, мне тоже показался прирост совсем незначительным. на 2500 записях я никакого прироста не ощутил. но методы поправил.
кстати, вопрос методологический: а зачем вообще удалять строки из инв. журнала?
__________________
Felix nihil admirari |
|
10.02.2010, 20:57 | #6 |
Участник
|
Как раз наоборот. Много мелких транзакций в цикле выполняются заметно дольше, чем одна общая транзакция на весь цикл. Время тратится на отдельное открытие-закрытие каждой мелкой транзакции.
|
|
10.02.2010, 21:32 | #7 |
Administrator
|
... но при этом на больших объемах данных и при многопользовательской работе это ставит БД колом на время выполнения транзакции. Хотя формально получается быстрее (аналогично тому, что цикл с прогресс-баром крутится медленнее, чем без него, но при этом психологически кажется что быстрее)
__________________
Возможно сделать все. Вопрос времени |
|
10.02.2010, 22:52 | #8 |
Участник
|
А смысл разносить фактическое нувое количество если по системе также 0?
|
|
10.02.2010, 22:54 | #9 |
Участник
|
а поразвёртнутей можно? я не компетентен в вопросе настолько, чтоб из вопроса на вопрос составить себе ответ.
__________________
Felix nihil admirari |
|
11.02.2010, 11:15 | #10 |
Участник
|
Цитата:
Также могут начать возникать блокировки чтения (правда зависит от версии системы и уровня изоляции при чтении - READ_COMMITTED_SNAPSHOT в SQL 2005 говорят проблему эту решает) И если транзакция будет длится, скажем, 4 часа, но через 3:59 выключат свет в серверной , то после перезагрузки 4 часа БД будет недоступна, пытаясь откатить все эти изменения. То же будет в случае отката по ошибки в процессе обработки (я думаю, что именно по этой причине там сделали создание журнала с ошибками вместо отката всех строк, как в заказах на покупку/продажу). Поэтому время на открытия/закрытия мелких транзакций выгоднее с точки зрения скорости. Но целостность данных дороже. |
|
11.02.2010, 11:24 | #11 |
Участник
|
Цитата:
Такие строки и удаляются |
|
11.02.2010, 12:17 | #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 полю. Для индекса по нескольким полям, тем более строковым, разница будет еще больше. |
|
11.02.2010, 16:55 | #13 |
Участник
|
практически я уже переписал методы на всех этих таблицах, как учили в школе.
интересно, много ли ещё таких мест к оптимизации? можно их как-то все автоматически найти?
__________________
Felix nihil admirari |
|
12.02.2010, 15:01 | #14 |
Участник
|
Совершенно верно, именно это я и собирался сказать.
|
|
Теги |
inventjournal, оптимизация, производительность, запрос (query) |
|
|