|
10.03.2016, 13:11 | #1 |
Участник
|
Почему запрос CustTransOpen именно такой?
Давно интересовал вопрос. А сейчас столкнулся снова.
А почему запрос CustTransOpen определен в AOT\Query именно в таком порядке? Почему внутри CustTable находится CustTransOpen, а уже к нему прицеплен CustTrans? да, я в курсе, что в SQL запросе все это отобразиться в inner join и серверу SQL все равно в каком порядке. Но аксапте то не все равно. аксапта генерит relation между соседними таблицами. эти связи идут в запрос. у аксапты есть метод change. у аксапты есть хинт forcenested. для аксапты порядок важен. почему в Query именно такой порядок таблиц? |
|
10.03.2016, 13:15 | #2 |
Участник
|
Мне кажется, идея была в том, что надо максимально эффективно сужать выборку. Видимо, "автору" запроса показалось, что лучше всего сужают выборку фильтры по клиентам, затем - по открытым проводкам, а уже потом - по всем подряд проводкам. А что оптимизатор запросов умеет менять порядок объединения таблиц в запросе, при этом не учитывалось.
Последний раз редактировалось gl00mie; 10.03.2016 в 13:32. |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
10.03.2016, 13:25 | #3 |
Moderator
|
Цитата:
Сообщение от gl00mie
Мне кажется, идея была в том, что надо максимально эффективно сужать выборку. Видимо, "автору" запроса показалось, что лучше всего сужают выборку фильтры по клиентам, затем - по открытым проводкам, а уже потом - по всем подряд проводкам. И что оптимизатор запросов умеет менять местами порядок объединения таблиц в запросе, при этом не учитывалось.
|
|
10.03.2016, 13:45 | #4 |
Участник
|
хм... уточню. интересует не столько "почему CustTable первая",
сколько "почему вторая CustTransOpen" вроде естественный логический порядок: CustTable - CustTrans - CustTransOpen но здесь порядок неестественно вывернут. да, согласен, что это очень старый объект. старый как гавно мамонта. да, согласен, что скорее всего имела место какая-то оптимизация. вопрос - какая именно? почему именно так? просто не вижу никаких преимуществ от такого порядка по сравнению с естественным. а после введения договоров в custTrans, запрос вообще стал... "все в неестественных позах. наверное, что-то случилось" (С) http://www.youtube.com/watch?v=doeTUFRu3-A |
|
10.03.2016, 14:26 | #5 |
Участник
|
Может это из-за того, что к CustTrans потом пользователи могут приджойнить другие таблицы, например, LedgerTrans, а потом к этой другой таблице еще чего-нибудь приджойнить.
А если последней сделать таблицу к CustTransOpen, то к ней мало что можно приджойнить. А к непоследней таблице в Query нельзя джойнить более одной таблицы, так как в этом случае Query начинает неправильно работать. Важно, чтобы самой последней в запросе была наиболее универсальная таблица, имеющая наибольшее количество логических связей с остальной системой. Пример: X++: //Вариант 1) - который будет работать: CustTable | ------>CustTransOpen | ----------------->CustTrans | -------------->LedgerTrans | ----------->LedgerTable //Вариант 2) - который не будет работать: CustTable | ------->CustTrans | -------------->LedgerTrans | | | ----------->LedgerTable |-------------->CustTransOpen Последний раз редактировалось Ace of Database; 10.03.2016 в 14:39. |
|
|
За это сообщение автора поблагодарили: mazzy (5), gl00mie (2). |
10.03.2016, 14:45 | #6 |
Участник
|
Цитата:
Тогда все логично. В рамках одного клиента количество записей в CustTransOpen должно быть существенно меньше, чем количество записей в CustTrans.
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
10.03.2016, 14:56 | #7 |
Участник
|
В поддержку моей теории попробуйте выполнить следующий джоб.
Видно, что если таблица CustTrans непоследняя, и к ней приджойнить другие таблицы, то Аксапта генерирует неправильный запрос. X++: static void Job782(Args _args) { Query query = new Query(); QueryRun queryRun; QueryBuildDatasource qbdsCustTable; QueryBuildDatasource qbdsCustTrans; QueryBuildDatasource qbdsCustTransOpen; QueryBuildDatasource qbdsLedgerTrans; QueryBuildDatasource qbdsLedgerTable; ; //-->правильно работает query = new Query(); qbdsCustTable = query.addDataSource(tableNum(CustTable)); qbdsCustTransOpen = qbdsCustTable.addDataSource(tableNum(CustTransOpen)); qbdsCustTrans = qbdsCustTransOpen.addDataSource(tableNum(CustTrans)); qbdsLedgerTrans = qbdsCustTrans.addDataSource(tableNum(LedgerTrans)); qbdsLedgerTable = qbdsLedgerTrans.addDataSource(tableNum(LedgerTable)); queryRun = new QueryRun(query); info(queryRun.query().dataSourceNo(1).toString()); //<--правильно работает //-->неправильно работает query = new Query(); qbdsCustTable = query.addDataSource(tableNum(CustTable)); qbdsCustTrans = qbdsCustTable.addDataSource(tableNum(CustTrans)); qbdsCustTransOpen = qbdsCustTrans.addDataSource(tableNum(CustTransOpen)); qbdsLedgerTrans = qbdsCustTrans.addDataSource(tableNum(LedgerTrans)); qbdsLedgerTable = qbdsLedgerTrans.addDataSource(tableNum(LedgerTable)); queryRun = new QueryRun(query); info(queryRun.query().dataSourceNo(1).toString()); //<--неправильно работает } Последний раз редактировалось Ace of Database; 10.03.2016 в 15:04. |
|
|
За это сообщение автора поблагодарили: mazzy (2), Ruff (2). |
10.03.2016, 14:59 | #8 |
Участник
|
Авторы запроса специально оставили удобную "розетку", через которую можно подключать новые таблицы к запросу.
Запросы в Аксапте - это как поезд, в котором таблицы выполняют роль вагонов. Последним ставят самый красивый вагон, чтобы было приятно к нему прицеплять новые вагоны А таблица CustTransOpen - это аппендикс, к нему мало что подцепишь, и поэтому ее не оставили в самом конце. Последний раз редактировалось Ace of Database; 10.03.2016 в 15:03. |
|
10.03.2016, 15:11 | #9 |
Участник
|
А если поставить fetchMode(fetchMode::one2one) ?
Последний раз редактировалось mazzy; 10.03.2016 в 15:18. Причина: исправил смайлик |
|
|
За это сообщение автора поблагодарили: Ace of Database (5). |
10.03.2016, 15:21 | #10 |
Участник
|
One2One правильно работает.
Но на формах вроде бы нельзя в свойствах датасурса изменить FetchMode. На query можно, на формах - нельзя. |
|
10.03.2016, 15:27 | #11 |
Участник
|
Фишка в том, что свойство fetchMode можно установить только у подчиненного датасорса.
А на форме нет иерархии в источниках данных. Поэтому на форме этого сделать нельзя. По крайней мере так было в AX2009. |
|
10.03.2016, 15:45 | #12 |
Участник
|
Разрешите ещё позанудствовать. В AX2009 уже можно прописать конкретный Query в свойствах корневого узла Data Sources. Собственно все новые формы, которые *ListPage по такому принципу и сделаны.
|
|
|
За это сообщение автора поблагодарили: Ace of Database (5). |
10.03.2016, 15:56 | #13 |
Участник
|
С использованием этой технологии все равно все таблицы разворачиваются в плоскую одноуровневую иерархию на форме, без подчиненных датасорсов, у которых можно было бы изменить свойство FetchMode. И я сомневаюсь, что форма на лету подхватит значение этого свойства из прописанного query в корневом узле Data Sources
|
|
10.03.2016, 16:13 | #14 |
Участник
|
Хотя нет, свойство FetchMode наблюдается при таком подходе
|
|
10.03.2016, 19:03 | #15 |
Участник
|
Возможно данные из CustTrans'а изначально вообще не предполагали забирать.
Первые два DS содержат узел Sorting(+ св-во update выставлено в true), которого нет в третьем DS, и соответственно сейчас его вообще нет в новых объектах Query, так что его могли попросту добавить уже после того как изначально сформировали сам объект, при этом уже потом не захотели менять порядок. PS. Попытка добавить узел Order by для данного запроса приводит к ошибке - Сочетание сортировки старого типа и новых предложений Group By или Order By в рамках одного запроса не допускается.
__________________
Sergey Nefedov |
|
|
За это сообщение автора поблагодарили: mazzy (2). |