AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
DAX
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 10.03.2016, 13:11   #1  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Почему запрос CustTransOpen именно такой?
Давно интересовал вопрос. А сейчас столкнулся снова.

А почему запрос CustTransOpen определен в AOT\Query именно в таком порядке?
Почему внутри CustTable находится CustTransOpen, а уже к нему прицеплен CustTrans?

да, я в курсе, что в SQL запросе все это отобразиться в inner join и серверу SQL все равно в каком порядке.
Но аксапте то не все равно.

аксапта генерит relation между соседними таблицами. эти связи идут в запрос.
у аксапты есть метод change.
у аксапты есть хинт forcenested.
для аксапты порядок важен.

почему в Query именно такой порядок таблиц?
Изображения
 
Старый 10.03.2016, 13:15   #2  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Мне кажется, идея была в том, что надо максимально эффективно сужать выборку. Видимо, "автору" запроса показалось, что лучше всего сужают выборку фильтры по клиентам, затем - по открытым проводкам, а уже потом - по всем подряд проводкам. А что оптимизатор запросов умеет менять порядок объединения таблиц в запросе, при этом не учитывалось.

Последний раз редактировалось gl00mie; 10.03.2016 в 13:32.
За это сообщение автора поблагодарили: mazzy (2).
Старый 10.03.2016, 13:25   #3  
online
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,890 / 5647 (194) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Мне кажется, идея была в том, что надо максимально эффективно сужать выборку. Видимо, "автору" запроса показалось, что лучше всего сужают выборку фильтры по клиентам, затем - по открытым проводкам, а уже потом - по всем подряд проводкам. И что оптимизатор запросов умеет менять местами порядок объединения таблиц в запросе, при этом не учитывалось.
И, возможно, в момент написания запроса, основной БД была внутренняя Database Engine Дамгаарда, которая не факт что особо хорошо умела запросы оптимизировать. Отсюда же и indexHint во всех find()/exists() методах может рости.
Старый 10.03.2016, 13:45   #4  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
хм... уточню. интересует не столько "почему CustTable первая",
сколько "почему вторая CustTransOpen"

вроде естественный логический порядок: CustTable - CustTrans - CustTransOpen
но здесь порядок неестественно вывернут.

да, согласен, что это очень старый объект. старый как гавно мамонта.
да, согласен, что скорее всего имела место какая-то оптимизация.
вопрос - какая именно? почему именно так?

просто не вижу никаких преимуществ от такого порядка по сравнению с естественным.
а после введения договоров в custTrans, запрос вообще стал...

"все в неестественных позах. наверное, что-то случилось" (С)
http://www.youtube.com/watch?v=doeTUFRu3-A
Старый 10.03.2016, 14:26   #5  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Может это из-за того, что к 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  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от mazzy Посмотреть сообщение
хм... уточню. интересует не столько "почему CustTable первая", сколько "почему вторая CustTransOpen"

вроде естественный логический порядок: CustTable - CustTrans - CustTransOpen но здесь порядок неестественно вывернут.
Так gl00mie сделал вполне логичное предположение. Автор запроса, предположительно, думал, что механизм SQL-запросов работает по принципу вложенных циклов (а может, первые версии Damgaard так и работали ).

Тогда все логично. В рамках одного клиента количество записей в CustTransOpen должно быть существенно меньше, чем количество записей в CustTrans.
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
За это сообщение автора поблагодарили: mazzy (2).
Старый 10.03.2016, 14:56   #7  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
В поддержку моей теории попробуйте выполнить следующий джоб.
Видно, что если таблица 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  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Авторы запроса специально оставили удобную "розетку", через которую можно подключать новые таблицы к запросу.
Запросы в Аксапте - это как поезд, в котором таблицы выполняют роль вагонов. Последним ставят самый красивый вагон, чтобы было приятно к нему прицеплять новые вагоны
А таблица CustTransOpen - это аппендикс, к нему мало что подцепишь, и поэтому ее не оставили в самом конце.

Последний раз редактировалось Ace of Database; 10.03.2016 в 15:03.
Старый 10.03.2016, 15:11   #9  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,867 / 3123 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
В поддержку моей теории попробуйте выполнить следующий джоб.
А если поставить fetchMode(fetchMode::one2one) ?

Последний раз редактировалось mazzy; 10.03.2016 в 15:18. Причина: исправил смайлик
За это сообщение автора поблагодарили: Ace of Database (5).
Старый 10.03.2016, 15:21   #10  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
One2One правильно работает.
Но на формах вроде бы нельзя в свойствах датасурса изменить FetchMode.
На query можно, на формах - нельзя.
Старый 10.03.2016, 15:26   #11  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
Но на формах вроде бы нельзя в свойствах датасурса изменить FetchMode. На query можно, на формах - нельзя.
На формах добавляемые источники цепляются через ExistsJoin
Старый 10.03.2016, 15:27   #12  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Фишка в том, что свойство fetchMode можно установить только у подчиненного датасорса.
А на форме нет иерархии в источниках данных. Поэтому на форме этого сделать нельзя.
По крайней мере так было в AX2009.
Старый 10.03.2016, 15:29   #13  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
На формах добавляемые источники цепляются через ExistsJoin
А как же тогда из них выводить данные в контролы на форме?
Старый 10.03.2016, 15:33   #14  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
А как же тогда из них выводить данные в контролы на форме?
Я думал вы о пользовательских фильтрах Ctrl+F3
Старый 10.03.2016, 15:37   #15  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Нет, я в первую очередь с точки зрения разработчика думал.
Для разработчиков сделали такой шаблон запроса, чтобы он без изменений в базовой своей части и на формах мог использоваться.
Старый 10.03.2016, 15:45   #16  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,427 / 1771 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
Фишка в том, что свойство fetchMode можно установить только у подчиненного датасорса.
А на форме нет иерархии в источниках данных. Поэтому на форме этого сделать нельзя.
По крайней мере так было в AX2009.
Разрешите ещё позанудствовать. В AX2009 уже можно прописать конкретный Query в свойствах корневого узла Data Sources. Собственно все новые формы, которые *ListPage по такому принципу и сделаны.
За это сообщение автора поблагодарили: Ace of Database (5).
Старый 10.03.2016, 15:56   #17  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Разрешите ещё позанудствовать. В AX2009 уже можно прописать конкретный Query в свойствах корневого узла Data Sources. Собственно все новые формы, которые *ListPage по такому принципу и сделаны.
С использованием этой технологии все равно все таблицы разворачиваются в плоскую одноуровневую иерархию на форме, без подчиненных датасорсов, у которых можно было бы изменить свойство FetchMode. И я сомневаюсь, что форма на лету подхватит значение этого свойства из прописанного query в корневом узле Data Sources
Старый 10.03.2016, 16:13   #18  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
870 / 637 (23) +++++++
Регистрация: 14.10.2004
Хотя нет, свойство FetchMode наблюдается при таком подходе
Миниатюры
Нажмите на изображение для увеличения
Название: FetchMode.png
Просмотров: 401
Размер:	43.3 Кб
ID:	9532  
Старый 10.03.2016, 19:03   #19  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
362 / 542 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
Возможно данные из CustTrans'а изначально вообще не предполагали забирать.

Первые два DS содержат узел Sorting(+ св-во update выставлено в true), которого нет в третьем DS, и соответственно сейчас его вообще нет в новых объектах Query, так что его могли попросту добавить уже после того как изначально сформировали сам объект, при этом уже потом не захотели менять порядок.

PS. Попытка добавить узел Order by для данного запроса приводит к ошибке - Сочетание сортировки старого типа и новых предложений Group By или Order By в рамках одного запроса не допускается.
__________________
Sergey Nefedov
За это сообщение автора поблагодарили: mazzy (2).
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Как класс->запрос->форма. Как такое создать? kitty DAX: Программирование 16 09.09.2014 12:52
Почему не работает запрос? vikuss2006 DAX: Программирование 4 07.04.2014 17:43
Вложенный запрос SQL с помощью великого Query user_ax DAX: Программирование 9 07.10.2013 14:00
Вставка queryRun-а в запрос sql user_ax DAX: Программирование 8 04.10.2013 17:21
Возможен ли такой Query kalex DAX: Программирование 4 07.05.2007 13:13
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 11:07.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.