Показать сообщение отдельно
Старый 23.04.2011, 00:51   #1  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
оптимизация запроса статистики по клиенту
последние трое суток провёл в занимательном чтении топиков с названиями вида "оптимизация запроса", но так и не нашёл ответа на свой вопрос. точнее, на несколько. озвучу их, плавно переходя от частного к общему. (дело происходит в AX2009+SQL2005)

на форме таблицы клиентов есть кнопочка запросов, среди которых есть "статистика". в нём отображается общее количество счетов-фактуров и проч. в заданных (5) периодах времени. так вот этот запрос формируется на одном и том же клиенте иной раз до 15 минут. посольку заказчик любит "запущать" это дело по нескольку раз на дню, его это сильно печалит.

судя по информации из таблицы логов sql в ax, основные "затыки" происходят в методе calcTotals в двух местах: там где идёт while select custTrans exists join ledgerTrans и ещё более вложенной конструкции.

1. можно ли как-то переписать данный запрос путём указания индексов, указания, какие именно поля нужно выбирать и проч?

2. нужно ли "шаманить" на sql сервере путём настроек или увеличения мощностей.

3. как в общем случае определять точку приложения усилий по решению подобных проблем с производительностью: код, скл-сервер, железо, архитектура? я понимаю, что нужно комплексно подходить, но меня интересует некий "алгоритм", который используется уважаемыми коллегами в их повседневной практике.


код "узкого места" класса:

X++:
    while select custTrans
        where custTrans.AccountNum          == custTable.AccountNum                     &&
              custTrans.TransDate           >= tmpStatPer.StartDate                     &&
              custTrans.TransDate           <= tmpStatPer.EndDate                       &&
//              custTrans.amountCur           <  0                                        &&
              custTrans.Invoice             == ''
        exists join ledgerTrans
            where ledgerTrans.TransDate     == custTrans.TransDate                      &&
                  ledgerTrans.Voucher       == custTrans.Voucher                        &&
                  (ledgerTrans.Posting      == LedgerPostingType::CustPayment   ||
                   ledgerTrans.Posting      == LedgerPostingType::CustBalance)
    {
        bankAccountTrans = BankAccountTrans::find(ledgerTrans.PaymReference);

        if (!bankAccountTrans || bankAccountTrans.BankTransType != BankParameters::find().nsfTransactionType)
        {
            if (custTrans.AmountCur <  0)
            {
                tmpStatPer.PaymQty ++;
            }
            else
            {
                tmpStatPer.PaymQty --;
            }

            tmpStatPer.PaymTotal        += -custTrans.AmountMST;

            while select custSettlement
                where custSettlement.TransRecId     == custTrans.RecId &&
                      custSettlement.OffsetTransVoucher
            {
                while select crossCompany custOffsetTrans
                    where custOffsetTrans.AccountNum     == custSettlement.OffsetAccountNum     &&
                          custOffsetTrans.Voucher        == custSettlement.OffsetTransVoucher   &&
                          custOffsetTrans.DataAreaId     == custSettlement.OffsetCompany        &&
                          custOffsetTrans.Invoice
                {
                    numOfInvoices               ++;
                    tmpStatPer.AveragePaymDays  += (custTrans.TransDate- custOffsetTrans.TransDate);
                }
            }
        }
    }
большое спасибо!
__________________
Felix nihil admirari

Последний раз редактировалось wojzeh; 27.10.2019 в 19:35.