Ни для кого не является секретом, что при настройке в ГФО выборки оборотов по счетам в корреспонденции с другими счетами работа ГФО становится не очень быстрой.
Раньше мы мирились с данной особенностью, но, в последнее время, пользователей стали эти особенности раздражать, пришлось искать методы оптимизации.
Формирование запроса на выборку в условиях корреспонденции производится в методе
initQuery класса
LedgerRRGOp_Ledger_Trans_RU. В DAX4 у нас загружены практически все изменения, существовавшие на момент прекращения поддержки DAX4. Ветка, которая относится к формированию запроса по корреспонденции
X++:
case LedgerRRGOperationType_RU::TurnoverInCorr:
case LedgerRRGOperationType_RU::TurnoverInCorrDebit:
case LedgerRRGOperationType_RU::TurnoverInCorrCredit:
В стандарте выглядит так:
X++:
this.addTransDateRange(parms.transDatePeriodFilter(baseDate));
this.addRange(fieldnum(LedgerTrans, BondBatch_RU), SysQuery::valueNotEmptyString());
this.addRange(fieldnum(LedgerTrans, BondBatchTrans_RU), SysQuery::valueNotEmptyString());
offsetQueryBuildDatasource = queryBuildDataSource.addDataSource(tablenum(LedgerTrans));
offsetQueryBuildDatasource.joinMode(JoinMode::ExistsJoin);
offsetQueryBuildDatasource.addLink(fieldnum(LedgerTrans, TransDate), fieldnum(LedgerTrans, TransDate));
offsetQueryBuildDatasource.addLink(fieldnum(LedgerTrans, Voucher), fieldnum(LedgerTrans, Voucher));
offsetQueryBuildDatasource.addLink(fieldnum(LedgerTrans, BondBatch_RU), fieldnum(LedgerTrans, BondBatch_RU));
offsetQueryBuildDatasource.addLink(fieldnum(LedgerTrans, BondBatchTrans_RU), fieldnum(LedgerTrans, BondBatchTrans_RU));
offsetQueryBuildDatasource.addRange(fieldnum(LedgerTrans, AccountNum)).value(parms.offsetAccountFilter());
offsetQueryBuildDatasource.addRange(fieldnum(LedgerTrans, PeriodCode)).value(SysQuery::value(PeriodCode::Regular));
offsetQueryBuildDatasource.addRange(fieldnum(LedgerTrans, Crediting)).value(#CreditingQueryValue);
После оптимизации эта ветка выглядит так:
X++:
this.addTransDateRange(parms.transDatePeriodFilter());
this.addRange(fieldnum(LedgerTrans, BondBatch_RU), SysQuery::valueNotEmptyString());
this.addRange(fieldnum(LedgerTrans, BondBatchTrans_RU), SysQuery::valueNotEmptyString());
offsetQueryBuildDatasource = queryBuildDataSource.addDataSource(tablenum(LedgerTrans));
// Изменил соединение с Exist на Inner с группировкой по RecId, убрал лишние условия соединения
// Добавил подсказки на Query по порядку обработки таблиц запроса
offsetQueryBuildDatasource.joinMode(JoinMode::InnerJoin);
offsetQueryBuildDatasource.addSelectionField(fieldNum(LedgerTrans, RecId), SelectionField::Min);
offsetQueryBuildDatasource.orderMode(OrderMode::GroupBy);
query.forceSelectOrder(true);
query.forceNestedLoop(true);
offsetQueryBuildDatasource.addLink(fieldnum(LedgerTrans, BondBatch_RU), fieldnum(LedgerTrans, BondBatch_RU));
offsetQueryBuildDatasource.addLink(fieldnum(LedgerTrans, BondBatchTrans_RU), fieldnum(LedgerTrans, BondBatchTrans_RU));
offsetQueryBuildDatasource.addRange(fieldnum(LedgerTrans, AccountNum)).value(parms.offsetAccountFilter());
offsetQueryBuildDatasource.addRange(fieldnum(LedgerTrans, PeriodCode)).value(SysQuery::value(PeriodCode::Regular));
offsetQueryBuildDatasource.addRange(fieldnum(LedgerTrans, Crediting)).value(#CreditingQueryValue);
Как видно из приведенного кода, выполнены следующие изменения:
- Изменен тип соединения и, на всякий случай, в связаннойм запросе сделана группировка.
- Оптимизатору дана подсказка по поводу порядка выборки данных таблиц.
- Убраны лишние условия соединения.
Мониторинг запросов в MS SQL показал:
- В исходном варианте в случае выборки по 3-5 счетам главной таблицы и 2-3 счетам корреспонденции среднее время выборки по одной строке ГФО составляло 15000-26000 миллисекунд.
- После изменения типа соединения среднее время составляло 2000 - 5000 миллисекунд.
- После добавления подсказки оптимизатору среднее время сократилось до 90-150 миллисекунд.
В итоге время формирования отчета вместо 30-90 минут стало в районе 5-10 минут. Вроде бы проблему решили, но переносить эти изменения в рабочую базу как-то страшно.
В настройке наших отчетов данные до изменения и после изменения выдаются одни и те же, только кратно ускорилась работа отчета. Боюсь, что я что-то не учел и на других настройках ГФО просто начнет выдавать неправильные данные.
Просьба, если у кого-либо будет время, проанализировать эти изменения с точки зрения того, что может быть нарушено.