|
06.11.2008, 18:30 | #1 |
Модератор
|
Оптимизация кода с LedgerTrans
Есть в Axapte 3 SP6 class LedgerRRGOperationBalanceTotal_RU метод
X++: public AmountMST calc() { AmountMST sumTmp, balanceAmountMST; balanceAmountMST = 0; if (m_PEriodType == LedgerRRGBalancePeriodType_RU::Incoming) m_CalculateDate -= 1; while select m_AccountList outer join m_LedgerTrans where m_LedgerTrans.TransDate <= m_CalculateDate && m_AccountList.AccountNum == m_LedgerTrans.AccountNum && m_LedgerTrans.PeriodCode == PeriodCode::Regular { if (this.checkTransaction(m_LedgerTrans.TransType, m_LedgerTrans.OperationsTax, m_LedgerTrans.Correct, m_LedgerTrans.Dimension, '')) { if (m_currencyForCalc == LedgerRRGCurrencyForCalc_RU::AmountMST) { sumTmp = m_LedgerTrans.AmountMST; } else { sumTmp = m_LedgerTrans.AmountMSTSecond; } balanceAmountMST += (m_AccountList.ReverseSign ? (-1) : 1) * sumTmp; } } return balanceAmountMST; } |
|
06.11.2008, 19:05 | #2 |
Участник
|
Цитата:
Во-вторых, прекратить извращение с суммированием от начала времен и использовать промежуточные итоги из LedgerBalancesDimTrans. |
|
06.11.2008, 19:10 | #3 |
NavAx
|
В-третьих, использовать sum() и group by.
В-четвертых, перенести генератор из DAX 4. |
|
|
За это сообщение автора поблагодарили: gl00mie (2). |
06.11.2008, 21:01 | #4 |
Member
|
Цитата:
Сообщение от raz
В-четвертых, перенести генератор из DAX 4.
Там одно только сокращение выбираемых для каждой записи полей само по себе уже даст ощутимый прирост производительности. Но в 4.0 был реализован комплекс мер по повышению производительности. Глупо было бы не перенести. Тем более, что там функционал развивают.
__________________
С уважением, glibs® |
|
07.11.2008, 09:04 | #5 |
Участник
|
Цитата:
Но гораздо больший прирост даст отсутствие перехваченного метода postload, а следовательно запрос будет целиком исполняться на SQL-сервере |
|
07.11.2008, 09:16 | #6 |
Member
|
Цитата:
Сообщение от mazzy
...
запрос будет целиком исполняться на SQL-сервере ...
__________________
С уважением, glibs® |
|
07.11.2008, 09:31 | #7 |
Участник
|
текстовая строка "Select <Бла-бла-бла> from <Бла-бла-бла> ...", которая выполняется НА СЕРВЕРЕ.
поскольку у таблицы LedgerTrans переопределен метод postLoad, то умная Аксапта не посылает SQL-серверу запрос с просьбой посуммировать, а выбирает все записи по одной, применяет к каждой метод postLoad и суммирует сама. Поэтому для таблиц с перехваченным postLoad гораздо важнее сократить объем выборки, нежели делать агрегирование (raz, к великому сожалению для таблицы LeagerTrans ваш совет не очень помогает. Вот для других таблиц - да, очень полезный совет). Так вот. Русские отчеты написаны неправильно. Они не учитывают "особенность" таблицы LedgerTrans и суммируют "от начала времен". Что приводит к выборке в Аксапту каждой проводки из LedgerTrans, которая попадает в условие. Еще раз советую посмотреть как с этим вопросом справились в буржуйских финансовых отчетах. В буржуйских из LedgerTrans никогда не выбирается больше финансового периода - Большинство данных берется из промежуточных итогов. (надо также помнить, что финансовый период безболезненно можно разбить на несколько в случае чего) |
|
06.11.2008, 19:20 | #8 |
Модератор
|
mazzy по вашему outer joint тут вообще не нужен?
raz Цитата:
В-четвертых, перенести генератор из DAX 4.
|
|
06.11.2008, 20:15 | #9 |
Участник
|
|
|
06.11.2008, 19:25 | #10 |
Модератор
|
На сколько необходим вызов табличного метода postLoad() при каждом обращении к LedgerTrans ?
Деактивировать его можно или не нужно? |
|
06.11.2008, 19:49 | #11 |
NavAx
|
X++: public AmountMST calc() { AmountMST sumTmp, balanceAmountMST; balanceAmountMST = 0; if (m_PEriodType == LedgerRRGBalancePeriodType_RU::Incoming) m_CalculateDate -= 1; while select m_AccountList while select sum(AmountMST), sum(AmountMSTSecond) from m_LedgerTrans group by TransType, OperationsTax, Correct, Dimension where m_LedgerTrans.TransDate <= m_CalculateDate && m_LedgerTrans.AccountNum == m_AccountList.AccountNum && m_LedgerTrans.PeriodCode == PeriodCode::Regular { if (this.checkTransaction(m_LedgerTrans.TransType, m_LedgerTrans.OperationsTax, m_LedgerTrans.Correct, m_LedgerTrans.Dimension, '')) { if (m_currencyForCalc == LedgerRRGCurrencyForCalc_RU::AmountMST) { sumTmp = m_LedgerTrans.AmountMST; } else { sumTmp = m_LedgerTrans.AmountMSTSecond; } balanceAmountMST += (m_AccountList.ReverseSign ? (-1) : 1) * sumTmp; } } return balanceAmountMST; } Цитата:
вы уверены, что можно его из 4 в 3 перенести?
|
|
|
За это сообщение автора поблагодарили: Poleax (2). |
06.11.2008, 20:54 | #12 |
Участник
|
Это конечно, да...
Но снова суммирование идет от начала времен. Разберитесь как суммирует класс LedgerBalanceDim_CurrentMST и все семейство LedgerBalance* |
|
07.11.2008, 09:47 | #13 |
Member
|
Я тоже не буду спорить ...
Но если поставить брякпоинт в методе .postLoad(), то с помощью дебагера и счетных палочек можно убедиться, что этот вражеский метод вызывается для результата GROUP BY, а не для каждого LedgerTrans в отдельности.
__________________
С уважением, glibs® |
|
|
За это сообщение автора поблагодарили: mazzy (5). |
07.11.2008, 09:51 | #14 |
NavAx
|
Таким образом суммирование и группировка дают колоссальный эффект...
|
|
|
За это сообщение автора поблагодарили: mazzy (10). |
07.11.2008, 12:14 | #15 |
Участник
|
Все бы так "не спорили"
Я тут было хотел съехидничать по поводу упрощения задачи, про то, что в изначальном методе были офигительные Group by... Но просто проверил. ax3.0sp6, ax4.0sp2, ax2009. Результат одинаковый: Действительно группирует на сервере, невзирая на перекрытый метод PostLoad. Офигеть! X++: static void Job7(Args _args) { ledgertrans lt; ; while select sum(amountmst) from lt group by AccountNum, TransDate, PeriodCode, TransType, OperationsTax, Correct, Dimension where lt.AccountNum == "51.010" { print(lt.AmountMST); } } Интересно, когда поменяли? Ладно, спишем на мой старческий маразм. Спасибо вам огромное. Да. raz, ты прав! |
|
07.11.2008, 12:32 | #16 |
Участник
|
Но тем не менее, это не повод заставлять SQL суммировать от начала времен
Выборку все равно нужно сокращать. |
|
07.11.2008, 10:03 | #17 |
Member
|
Вообще, тема относительно русских финотчетов уже была раскрыта...
Генератор финансовых отчётов И даже обновление потом вышло.
__________________
С уважением, glibs® |
|
|
За это сообщение автора поблагодарили: Poleax (2). |
07.11.2008, 12:13 | #18 |
Модератор
|
Какая интересная большая тема получилась.
Raz спасибо, твой код ускорил вывод отчета, с 3 часов до 12 минут. P.S. Данные в отчетах одинаковые glibs Генератор финансовых отчётов Цитата:
2. Не то, чтобы радикально, но факт. Как это ни банально, но создание кластерных индексов на таблицах LedgerRRGAccountInterval_RU, LedgerRRGCellTable_RU, LedgerRRGDimensionInterval_RU, LedgerRRGOffsetAccountInterval_RU, LedgerRRGOperationTable_RU повышает скорость выборки данных для отчета. Еще раз повторю, что не радикально. Можно сказать даже не существенно на фоне вышеописанного. Ну и поставить EntireTable кэш на LedgerRRGReportTable_RU равно как и группу таблиц Group какой-нибудь вместо Misc тоже не помешает.
Последний раз редактировалось Poleax; 07.11.2008 в 12:25. |
|
Теги |
ledgertrans, отчет, производительность, ax3.0, финансовые движения |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|