|
24.11.2015, 17:06 | #1 |
Участник
|
AX 2012 R2 CU7 Исправление медленно закрывающейся формы сопосталений проводок по клиенту/поставщику, открытой из журнала ГК
При помощи Tracing утилиты обнаружил в методе CustVendPaymNote.buildPaymNote() очень медленно выполняющийся запрос:
X++: while select crossCompany RecId from specTrans order by specTrans.RecId where specTrans.SpecCompany == _specCompany && specTrans.SpecTableId == _specTableId && specTrans.SpecRecId == _specRecId join RecId from custVendTransOpen where custVendTransOpen.DataAreaId == specTrans.RefCompany && custVendTransOpen.TableId == specTrans.RefTableId && custVendTransOpen.RecId == specTrans.RefRecId join TransDate, DocumentNum, Invoice, PaymId, Voucher from custVendTrans where custVendTrans.RecId == custVendTransOpen.RefRecId Выполнил его рефакторинг: X++: while select crossCompany TransDate, DocumentNum, Invoice, PaymId, Voucher from custVendTrans join RecId from custVendTransOpen where custVendTransOpen.RefRecId == custVendTrans.RecId join RecId from specTrans where specTrans.RefCompany == custVendTransOpen.DataAreaId && specTrans.RefTableId == custVendTransOpen.TableId && specTrans.RefRecId == custVendTransOpen.RecId && specTrans.SpecCompany == _specCompany && specTrans.SpecTableId == _specTableId && specTrans.SpecRecId == _specRecId И создал на таблице SpecTrans индекс: X++: #SpecTransIdx PROPERTIES Name #SpecTransIdx ENDPROPERTIES INDEXFIELDS #SpecRecId #SpecTableId #SpecCompany #Partition #RecId #INCLUDEDCOLUMNPRESENT #RefRecId #INCLUDEDCOLUMNPRESENT #RefTableId #INCLUDEDCOLUMNPRESENT #RefCompany #INCLUDEDCOLUMNPRESENT ENDINDEXFIELDS До рефакторинга запрос выполнялся 12 сек, после - меньше 1 сек. Пролем в работе бизнес-логики пока не обнаружил. |
|
|
За это сообщение автора поблагодарили: Logger (3), plumbum (2). |
24.11.2015, 17:34 | #2 |
Участник
|
Хотел бы уточнить некот. аспекты.
1.За счет чего получился более быстрый запрос? (Происходил скан таблиц или оптимизатор SQL сбоил?) 2.Размер индекса может быть равным самим данным и больше(с включением полей прямо в индекс), что для вставки и обновлений тоже не очень. 3.Кол-во записей во всех талицах? 4.План запроса увидеть бы до и после.(Сколько записей ожидается, сколько обработано и т.п.) Последний раз редактировалось GannexMan; 24.11.2015 в 17:36. |
|
24.11.2015, 19:11 | #3 |
Участник
|
Это текст и план стандартного SQL зароса (новый индекс не отключал, т.к. на план выполнения он не повлиял):
X++: SELECT T1.RECID, T2.RECID, T2.DATAAREAID, T3.TRANSDATE, T3.DOCUMENTNUM, T3.INVOICE, T3.PAYMID, T3.VOUCHER, T3.DATAAREAID, T3.RECID FROM SPECTRANS T1 CROSS JOIN VENDTRANSOPEN T2 CROSS JOIN VENDTRANS T3 WHERE ((T1.PARTITION=5637144576) AND (((T1.SPECCOMPANY='DA1') AND (T1.SPECTABLEID=212)) AND (T1.SPECRECID=17852886295))) AND ((T2.PARTITION=5637144576) AND (((T2.DATAAREAID=T1.REFCOMPANY) AND (T1.REFTABLEID=866)) AND (T2.RECID=T1.REFRECID))) AND ((T3.PARTITION=5637144576) AND (T3.RECID=T2.REFRECID AND (T3.DATAAREAID = T2.DATAAREAID) AND (T3.PARTITION = T2.PARTITION))) ORDER BY T1.RECID А это текст и план отрефакторенного SQL зароса: X++: SELECT T1.TRANSDATE, T1.DOCUMENTNUM, T1.INVOICE, T1.PAYMID, T1.VOUCHER, T1.RECID, T2.RECID, T3.RECID FROM VENDTRANS T1 CROSS JOIN VENDTRANSOPEN T2 CROSS JOIN SPECTRANS T3 WHERE ((T1.PARTITION=5637144576) AND (T1.DATAAREAID='DA1')) AND (((T2.PARTITION=5637144576) AND (T2.DATAAREAID='DA1')) AND (T2.REFRECID=T1.RECID)) AND ((T3.PARTITION=5637144576) AND ((((((T3.REFCOMPANY=T2.DATAAREAID) AND (T3.REFTABLEID=866)) AND (T3.REFRECID=T2.RECID)) AND (T3.SPECCOMPANY='DA1')) AND (T3.SPECTABLEID=212)) AND (T3.SPECRECID=17852886295))) |
|
24.11.2015, 20:57 | #4 |
Участник
|
Думаю, что план запроса лучше не стал.
Если в первом варианте, было два кластерных индекса, то во втором только один. Получили Key Lookup и жесткий удар по производительности. Во втором случае одна и та же таблица VendTrans выдала разное кол-во записей. В последнем запросе явно указано для всех таблиц данные брать только из DA1, возможно это и объясняет поведение, оптимизатор ограничил кол-во записей по выбранной компании, а не по всем AND (T3.RECID=T2.REFRECID AND (T3.DATAAREAID = T2.DATAAREAID) AND (T3.PARTITION = T2.PARTITION))) Судя по тому, как был написан первоначальный запрос, складывается впечатление, что его "выгибали" так специально. Если, ограничить VendTrans явным указанием DATAAREAID, оригинальный запрос будет намного быстрей. Последний раз редактировалось GannexMan; 24.11.2015 в 21:02. |
|
|
За это сообщение автора поблагодарили: Morpheus (3). |
25.11.2015, 11:27 | #5 |
Участник
|
Key Lookup можно устранить, добавив IncludedColumn(s) поля в индекс.
Коллеги, у вас есть возможность проверить на ваших инсталляциях, быстро ли закрывается форма сопоставлений? Для теста необходимо создать в журнал ГК транзакцию платеж для клиента или поставщика и сопоставить ее с инвойсом при помощи меню Функции/Сопоставление на форме строк журнала ГК. После сопоставления закрыть форму и оценить, как быстро она закроется. |
|
25.11.2015, 11:44 | #6 |
Модератор
|
У меня на CU7 - быстро (DATAAREAIDLITERAL и PARTITIONLITERAL - включены)
__________________
-ТСЯ или -ТЬСЯ ? |
|
|
За это сообщение автора поблагодарили: Morpheus (3). |
25.11.2015, 08:10 | #7 |
Модератор
|
А отключение (если трасса была собрана верно) crosscompany было запланировано или это побочный эффект ? Просто помимо него и отключения дурацкой и ненужной сортировки по SpecTrans.RecId - никаких изменений в коде нет
__________________
-ТСЯ или -ТЬСЯ ? |
|
25.11.2015, 11:12 | #8 |
Участник
|
Цитата:
Порядок, в котором следуют таблицы, изменен. В итоге sql запрос изменился. |
|
25.11.2015, 11:38 | #9 |
Модератор
|
Ну давайте вместе посчитаем в трассах количество критериев WHERE по DATAAREAID на VENDTRANS и VENDTRANSOPEN. У меня получилось 0 до рефакторинга и 2 - после
__________________
-ТСЯ или -ТЬСЯ ? |
|
25.11.2015, 12:09 | #10 |
Участник
|
Нашел еще один похожий "медленный" запрос в методе LedgerJournalTransUpdateVend.checkSettleVoucher(), который вызывается при проверке/разноске журнала ГК содержащем сопоставленные проводки по клиенту или поставщику:
X++: while select crossCompany RecId from specTrans where specTrans.SpecCompany == _ledgerJournalTrans.company() && specTrans.SpecTableId == _ledgerJournalTrans.TableId && specTrans.SpecRecId == _ledgerJournalTrans.RecId join RecId from vendTransOpen where specTrans.RefCompany == vendTransOpen.DataAreaId && specTrans.RefTableId == vendTransOpen.TableId && specTrans.RefRecId == vendTransOpen.RecId join RecId, AccountNum, Voucher, Approved, Closed from vendTrans where vendTransOpen.RefRecId == vendTrans.RecId join Party from vendTransVendor where vendTrans.AccountNum == vendTransVendor.AccountNum |
|
25.11.2015, 14:49 | #11 |
Участник
|
@ZVV
Оба запроса - кросс компани. В первом через промежуточное условие и во втром, аксапта "вот так решила" сгенерировать запрос. В коде указано для каких компаний надо делать выборку, вот аксапта и указала явно. Видно не смогла "связать" условием как в первом варианте и стала перечислять компании. @Morpheus Куда копать? Сначала в план запроса. Смотрим, где макс. поток данных и пытаемся его ограничить. Последний раз редактировалось GannexMan; 25.11.2015 в 15:01. |
|
25.11.2015, 15:07 | #12 |
MCITP
|
Цитата:
В первом запросе нет никакого ограничения на SPECTRANS.REFCOMPANY, ни явно, ни через условия. Т.е. оно может быть любым и ссылаться на записи VendTrans(Open) в любой компании. Во втором же запросе неожиданно появляются эти явные ограничения T1/T2.DATAAREAID='DA1'
__________________
Zhirenkov Vitaly |
|
25.11.2015, 15:20 | #13 |
Модератор
|
Не-не-не, там все интересно. В оригинальном запросе фактически делается JOIN VendTrans с VendTransOpen
X++: AND (T3.DATAAREAID = T2.DATAAREAID) AND (T3.PARTITION = T2.PARTITION) X++: ((T1.PARTITION=5637144576) AND (T1.DATAAREAID='DA1')) AND (((T2.PARTITION=5637144576) AND (T2.DATAAREAID='DA1'))
__________________
-ТСЯ или -ТЬСЯ ? |
|
25.11.2015, 15:27 | #14 |
MCITP
|
Цитата:
но с чего он решил, что нужно только 'DA1' остаётся непонятным? если только автор привёл не все данные и это только "частичный" запрос по одной из компаний... не знаю умеет ли Аксапта так делать, но с чисто логической точки зрения после убирания сортировки это могло бы иметь некоторый смысл с точки зрения оптимизации...
__________________
Zhirenkov Vitaly |
|
25.11.2015, 15:40 | #15 |
Модератор
|
Очень похоже на косяк, потому что не должно было такого произойти - фильтр на SpecTrans.SpecCompany, а JOIN по RefCompany
Надо будет потестировать, мы тоже на CU7
__________________
-ТСЯ или -ТЬСЯ ? |
|
25.11.2015, 15:27 | #16 |
Участник
|
Цитата:
Сообщение от ZVV
Мне видится что вы не правы.
В первом запросе нет никакого ограничения на SPECTRANS.REFCOMPANY, ни явно, ни через условия. Т.е. оно может быть любым и ссылаться на записи VendTrans(Open) в любой компании. Во втором же запросе неожиданно появляются эти явные ограничения T1/T2.DATAAREAID='DA1' Последний раз редактировалось GannexMan; 25.11.2015 в 15:29. |
|
25.11.2015, 15:46 | #17 |
Участник
|
|
|
25.11.2015, 15:50 | #18 |
MCITP
|
Лучше б конечно протрэйсить, чтоб наверняка...
__________________
Zhirenkov Vitaly |
|
Теги |
ax2012r2, performance, slow, тормоза |
|
|