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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 11.01.2012, 23:13   #1  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,631 / 2128 (76) +++++++++
Регистрация: 13.06.2004
Адрес: Москва
AX 2012 Наследование таблиц. Краткое описание механизма
Добрый день! Пришлось тут в рамках подготовки к курсу 80299 What's New -Technical in Microsoft Dynamics AX 2012 for Development поисследовать AX 2012, и, поискав достаточно скудную информацию о наследовании таблиц (на русском – так вообще отсутствующую) – решил поисследовать самостоятельно – что же это за технология изнутри. Описанное ниже является исключительно моим мнением, не претендующим на истину в последней инстанции, и не являющееся заменой документации по данной функциональности.
Предназначение

Данная технология хорошо предназначена для разделения одной большой таблицы по полям на несколько маленьких (подразумевается вертикальное разделение – когда часть полей из большой таблицы «уезжает» в другую). Хорошим примером ситуации, когда наследование таблиц имеет смысл применять – являются таблицы InventJournalTrans / LedgerJournalTrans – строки журналов, в которых имеются поля, специфичные только для журналов определенного типа, а для остальных данных – они являются ненужными. Примером здесь могут являться поля, относящиеся к основным средствам (для LedgerJournalTrans) или поля, относящиеся к инвентаризации (для InventJournalTrans).
Принцип построения структуры таблиц в СУБД

Наследование таблиц, как технология – реализована в АХ 2012 по принципу абстрагирования программиста от СУБД (как в 1С), когда разработчик задает системе некоторые принципы, а ядро реализует эти принципы в СУБД и при исполнении кода. На самом деле – эта идеология (с т.з. структуры СУБД) уже была применена в АХ 2009 в таблицах InventJournalTrans и InventJournalTrans_Tag, а также в LedgerJournalTrans и LedgerJournalTrans_Asset, LedgerJournalTrans_Project, LedgerJournalTrans_RCash, LedgerJournalTrans_RAsset, LedgerJournalTrans_RDeferrals. Все эти таблицы связаны друг с другом отношением 1:0 или 1:1 (т.е. к примеру – в таблице LedgerJournalTrans_Asset может присутствовать только одна запись для одной записи в LedgerJournalTrans или же полностью отсутствовать, если запись в LedgerJournalTrans не имеет отношения к международным Осам). Связка осуществляется по RecId. Из этого списка несколько выпадают таблицы LedgerJournalTrans_RDeferrals (здесь в одной записи – ссылки на две разных записи в LedgerJornalTrans) и InventJournalTrans_Tag (здесь связь осуществляется по JournalId + LineNum, а не RecId). Кстати говоря, эти таблицы так и остались в АХ 2012 без иерархии (т.е. не состоящие в иерархии).
Таким образом, всю цепочку таблиц, участвующих в иерархии можно взять и заменить одной большой мегатаблицей, в полях которых будет много пустых данных. Поля в этой одной большой мегатаблице будут состоять из всех полей всех таблиц, участвующих в иерархии (за исключением, безусловно системных полей).
Состав функционала иерархии таблиц

В АХ 2012 под иерархией (наследованием) таблиц (Table Hierarchy, Table Inheritance) подразумевается:
· Функционал ядра, позволяющий строить структуру таблиц, описанную выше, связи между которыми будут осуществляться по RecId родительской таблицы (в нашем примере иерархия двухуровневая и родительскими таблицами являются это LedgerJournalTrans / InventJournalTrans). Важно! RecId производной таблицы совпадает с RecId базовой, т.о. в производной таблице может быть не более одной записи, соответствующей записи в базовой (родительской) таблице.
· Функционал наследования методов у производной таблицы (Derived Table) от ее родительской / базовой (Base Table)
· Функционал автоматического добавления всех базовых и производных таблиц на форму, при добавлении таблицы из иерархии на форму
· Функционал выбора производной таблицы на форме при создании записи (в таблицах, которые являются базовыми к добавляемой – запись создается автоматически при создании записи в таблице, прописанной в датасорсе. Задача разработчика – обеспечить возможность заполнения всех обязательных полей во всех таблицах иерархии при создании записи – иначе запись сохранена не будет).
· Механизм настройки иерархии таблиц в АОТ.
Запрос, генерирующийся к СУБД на форме

Запрос, генерирующийся к СУБД на форме содержит в себе все таблицы из иерархии – как производные, так и базовые (т.к. везде нужно добавлять одно и тоже значение RecId). Т.о. крупная иерархия (состоящая из большого количества таблиц) может привести к большому количеству джойнов, причем связи между таблицами осуществляются по LEFT OUTER JOIN, что не добавляет скорости к выборке (по сравнению с INNER JOIN). Поддержка сортировки и фильтрации таблиц, связанных по LEFT OUTER JOIN на форме появилась в AX 2012, поэтому эти данные можно на форме фильтровать / сортировать, как будто это одна большая мегатаблица.
«Академическим» примером наследования таблиц является глобальная адресная книга (DirPartyTable).
Название: DirPartyTableHierarhy.PNG
Просмотров: 3392

Размер: 7.1 Кб
Посмотрим, как это все будет выглядеть на форме. Для этого создадим простейшую форму, в которую добавим датасорс DirPartyTable
Название: DirPartyFormAOT.PNG
Просмотров: 2152

Размер: 25.2 Кб
И добавим грид с полями из разных таблиц:
DirPartyTable.Name
DirPerson.BirthMonth
DirPerson.BirthYear
DirPerson.BirthDay
DirOrganizationBase.PhoneticName
Название: DirPartyFormShow.PNG
Просмотров: 2126

Размер: 19.1 Кб
Поля, помеченные кружочком являются unretrieved, т.е. невыбираемыми (проще говоря, из-за LEFT JOIN там стоит значение NULL, т.к. запись в соответствующей таблице отсутствует). Пустые значения (без кружочка) означают наличие записи в соответствующей таблице и незаполненное поле. На скриншоте видно, что, например, для записи «Coho Receivers» в DirPartyTable отсутствует запись в таблице DirPerson, но присутствует запись в таблице DirOrganizationBase с пустым значением поля PhoneticName.
Запрос, отправляемый к СУБД в этом случае выглядит так:
Нажмите на изображение для увеличения
Название: DirPartyQueryDesign.PNG
Просмотров: 322
Размер:	49.0 Кб
ID:	7453
В виде T-SQL:
Нажмите на изображение для увеличения
Название: DirPartyQueryTSQL.PNG
Просмотров: 279
Размер:	58.9 Кб
ID:	7454
Если же мы вдруг решили добавить на форму таблицу из середины иерархии, к примеру OmInternalOrganization, то запрос к СУБД в этом случае будет выглядеть так:
Нажмите на изображение для увеличения
Название: HalfDirPartyQueryDesign.PNG
Просмотров: 232
Размер:	32.3 Кб
ID:	7456

В виде T-SQL:
Нажмите на изображение для увеличения
Название: HalfDirPartyQueryTSQL.PNG
Просмотров: 268
Размер:	11.4 Кб
ID:	7457
В этом примере наглядно видно, как из запроса исчезла таблица DirPerson, т.к. она не является ни базовой ни производной к таблице OmInternalOrganization. Также обращаю внимание на появление CROSS JOIN-ов к базовым таблицам.
Вопрос осмысленности добавления таблицы из середины иерархии я оставляю в стороне, т.к. цель данной статьи – показать, как это будет работать в различных вариантах исполнения. А понимание бизнес-применения наследования таблиц придет со временем.
Процедура создания иерархии таблиц

1. Создать обе таблицы (базовую и производную), как элементы в АОТ без дополнительных полей.
2. Создать в базовой таблице поле типа Int64, наследованное от типа \System Documentation\Types\RelationType и назвать его InstanceRelationType (должно быть точно такое название). В этом поле будет храниться код производной таблицы (TableId).
3. На базовой таблице включить свойство SupportInheritance = Yes и выбрать в свойстве InstanceRelationType одноименное только что созданное поле. Сохранить базовую таблицу.
Нажмите на изображение для увеличения
Название: BaseTableProperties.PNG
Просмотров: 206
Размер:	24.3 Кб
ID:	7448
4. На производной таблице включить свойство SupportInheritance = Yes и выбрать в свойстве Extends базовую таблицу. Автоматически создастся Relation на базовую таблицу. Сохранить производную таблицу.
Нажмите на изображение для увеличения
Название: DerivedTableProperties.PNG
Просмотров: 198
Размер:	23.9 Кб
ID:	7449
Свойства созданного Relation:
Нажмите на изображение для увеличения
Название: DerivedTableRelation.PNG
Просмотров: 212
Размер:	24.8 Кб
ID:	7450
5. Добавить остальные необходимые поля в базовую и производную таблицу.
Версия системы

Данная статья подготовлена по версии АХ 2012:
Kernel version: 6.0.947.0
Application version: 6.0.947.0

Обсуждение на форуме ранее

axdaily: Table inheritance
Наследование таблиц в 2012, кто нибудь уже использовал ?


Обновление для версии R2 и R3

В AX2012 R2 механизм наследования таблиц немного изменили.
На уровне АОТ механизм остался таким же как и был, а вот на уровне СУБД - теперь вся цепочка таблиц представляет собой одну большую базовую табличку, в которой собраны все поля из производных таблиц. Т.о. в вышеописанном примере все поля из таблички DirPerson и DirOrganizationBase "переехали" в DirPartyTable. А сами таблички исчезли из общего списка таблиц (их нет в БД; в т.ч. их описания нет в SQLDictionary).
В частности, теперь не стало таблички CompanyInfo, т.к. она также наследуется от DirPartyTable и, как следствие, все поля из этой таблички были перенесены в DirPartyTable.
Соответственно, все запросы (в т.ч. обновления данных) к БД упростились, т.к. теперь выборка осуществляется из одной таблицы, в случае подцепления любой таблицы из иерархии в датасорс формы.
Разница в выборке из производной таблицы и из базовой теперь лишь состоит в количестве полей, перечисленных в конструкции SELECT (при выборке в Х++ из производной таблицы - запрос к БД посылается к базовой таблице, но только по тем полям, которые перечислены в АОТе в производной таблице). Правда, выборка из производной таблицы дополнительно фильтруется по тем записям, которые относятся только к ней.
Т.е. запрос в Х++
X++:
select dirPerson
теперь уйдет в БД, как:
Нажмите на изображение для увеличения
Название: DirPerson.png
Просмотров: 249
Размер:	19.7 Кб
ID:	8097
Обращаю внимание на дополнительный фильтр по полю InstanceRelationType - он обеспечивает отбор только тех записей, которые должны относиться к DirPerson
А запрос в Х++
X++:
select dirPartyTable
теперь уйдет в БД, как:
Нажмите на изображение для увеличения
Название: DirPartyTable.png
Просмотров: 229
Размер:	34.1 Кб
ID:	8098
Данная информация справедлива для версии R2 CU1 (Ядро и приложение - 6.2.1000.156)
В версии R3 (Ядро и приложение - 6.3.164.0) никаких изменений по отношению к R2 по части данной статьи не произошло
__________________
Возможно сделать все. Вопрос времени

Последний раз редактировалось sukhanchik; 01.06.2014 в 13:59.
За это сообщение автора поблагодарили: lev (13), S.Kuskov (15), Evgeniy_R (1), Logger (10), TasmanianDevil (7), Pustik (5), macklakov (9), Владимир Максимов (5), BOAL (9), mazzy (5), Berty Wooster (1), Stitch_MS (3), ziva (2), ivas (2), AlGol (2), jeky (2), db (10), oip (5), McArrow (1), AK-76 (1), Aquarius (1), AvrDen (1), -Dmitry- (0), alex55 (1), IvanS (1).
Старый 12.01.2012, 08:34   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,136 / 1545 (58) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Спасибо большое. Ужасно интересно всё то, что не известно (С)
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
· Функционал наследования методов у производной таблицы (Derived Table) от ее родительской / базовой (Base Table)
Т.е. через курсор производной таблицы доступны методы базовой.
А можно ли их перекрывать? Доступны ли через курсор производной таблицы поля базовой таблицы?
Цитата:
Сообщение от sukhanchik Посмотреть сообщение
· Функционал автоматического добавления всех базовых и производных таблиц на форму, при добавлении таблицы из иерархии на форму
А тоже самое будет происходить при добавлении таблиц в Query? При создании Query в AOT? При создании Query программно?
Если просто в коде написать "select DirPerson;" будет ли автоматически выбран DirPartyTable?

Ещё прошу подтвердить или опровергнуть следующее высказывание:
Одна и таже запись базовой таблицы может быть связана с записями одновременно из нескольких прозводных таблиц одного уровня иерархии?
Старый 12.01.2012, 14:50   #4  
TasmanianDevil is offline
TasmanianDevil
Мрачный тип
Аватар для TasmanianDevil
Злыдни
 
780 / 307 (12) ++++++
Регистрация: 24.01.2005
Адрес: Томск
Интересная штука, но, судя по документации, реализовано с неким анально-ориентированным уклоном.
  1. RecId уникален в рамках таблицы
  2. генерация RecID в разные таблицы независимы
  3. Цитата:
    Сообщение от sukhanchik Посмотреть сообщение
    Важно! RecId производной таблицы совпадает с RecId базовой, т.о. в производной таблице может быть не более одной записи, соответствующей записи в базовой (родительской) таблице.

Какой-то один из трех не вписывается в картину наследования таблиц и этот отщепенец - второй пункт. От первого мы отказаться не можем, третий требуется для обеспечения связей в м-ду родителями и наследниками - остается признать, что механизм выдачи RecId в наследуемых таблицах требует некоей модификации, чтобы выполнялись первый и третий пункты.

Суть такой модификации - наследование RecId из базовой таблицы при вставке в наследуемые, при этом вот что получится при вставке в таблицу потомка нижнего уровня N, если для него нужен такой же RecId, как и у базовой:
  • Попытка вставки в наследника уровня N - запрос RecId от родителя (наследника уровня N-1)
  • Попытка вставки в наследника уровня N-1 - запрос RecId от родителя (наследника уровня N-2)
  • ...
  • Попытка вставки в наследника уровня 1 - запрос RecId от родителя (базовой таблицы)
  • Вставка в базовую таблицу (передача RecId потомку 1 уровня)
  • ...
  • Вставка в таблицу потомка уровня N-2 (передача RecId потомку N-1 уровня)
  • Вставка в таблицу потомка уровня N-1 (передача RecId потомку уровня N)
  • Вставка в таблицу потомка уровня N
Зачем эти лишние вызовы и ожидания? Только для выполнения странной связи по RecId с обоих сторон join'а ? Как скажется на быстродействии вставки и блокировках на SystemSequences подобный многоступенчатый механизм, гарантирующий выполнение уникальности RecId по таблице и равные RecId у связанных записей в таблицах потомков/родителей ?


Половину этих вызовов ( всех возвратов от базовой записи) можно было бы избежать, используя всего лишь еще одно , дополнительное у к уже имеющемуся полю InstanceRelationType, служебное поле-ссылку (какой-нибудь InstanceRelationRecId) в родительских таблицах на запись в таблице-наследнике.
Тогда вставка в самый нижний уровень не ждала бы вставок с верхнего уровня, а все служебные join можно было реализовать как

Select Родитель Left Outer Join
Потомок On Родитель.InstanceRelationType = Потомок.TableId And Родитель.InstanceRelationRecId = Потомок.RecId
.
__________________
Axapta will die, MorphX stay forever
За это сообщение автора поблагодарили: gl00mie (5).
Старый 12.01.2012, 18:42   #5  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,397 / 885 (32) +++++++
Регистрация: 13.01.2004
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Ещё прошу подтвердить или опровергнуть следующее высказывание:

Одна и таже запись базовой таблицы может быть связана с записями одновременно из нескольких прозводных таблиц одного уровня иерархии?
Вот из этой цитаты

Цитата:
Сообщение от sukhanchik Посмотреть сообщение
2. Создать в базовой таблице поле типа Int64, наследованное от типа \System Documentation\Types\RelationType и назвать его InstanceRelationType (должно быть точно такое название). В этом поле будет храниться код производной таблицы (TableId).

3. На базовой таблице включить свойство SupportInheritance = Yes и выбрать в свойстве InstanceRelationType одноименное только что созданное поле. Сохранить базовую таблицу.
Следует, что у главной таблицы может быть одна и только одна подчиненная. Т.е. допустимы только "линейные цепочки" наследования. Ветвление или "деревья" - невозможны.

Впрочем, не знаю, что это за тип RelationType. Может, в Ax2012 этот тип данных допускает хранение неких списков значений?
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
За это сообщение автора поблагодарили: S.Kuskov (2).
Старый 12.01.2012, 23:19   #6  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,631 / 2128 (76) +++++++++
Регистрация: 13.06.2004
Адрес: Москва
Добрый день! Прошу прощение за отсутствие днем – был занят – до компьютера добрался только вечером.
Итак, отвечаю:
1. Ссылку от belugin можно расширить на несколько White Paper (http://www.microsoft.com/download/en....aspx?id=20864). Все они лежат в открытом доступе. На самом деле, если ввести в поисковик фразу White Paper AX 2012 можно найти сразу несколько документов по АХ 2012.
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Ещё прошу подтвердить или опровергнуть следующее высказывание:
Одна и таже запись базовой таблицы может быть связана с записями одновременно из нескольких прозводных таблиц одного уровня иерархии?
2. У главной таблицы может быть несколько подчиненных. Именно для этого и реализовано поле InstanceRelationType типа Int64 в базовой таблице, чтобы можно было по связке [InstanceRelationType, RecId] найти нужную запись в нужной производной таблице. Т.е. код таблицы определяется по полю InstanceRelationType, а RecId как я уже писал выше равны у базовой и производной таблицы. Однако, у одной записи в базовой таблице может быть только одна запись в производной таблице. Это следует как из структуры таблицы и запроса T-SQL, так и из диалога, который возникает при создании записи:
Название: CreateRecord.PNG
Просмотров: 2087

Размер: 17.0 Кб
Об этом говорил еще gigz в своем посте
3. Зачем было сделано равенство RecId между базовой и производной таблицами я не знаю. Но факты – вещь упрямая. Запрос в БД уходит таким, как я показал на скриншотах.
4. Абстрактные таблицы (свойство у таблицы Abstract = Yes). Я о них не стал писать, т.к. в документации сказано так: Any attempt to create a record and insert it in an abstract table will result in a run-time error. (Любые попытки создать запись и вставить ее в абстрактную таблицу приведет к ошибке выполнения). Однако, записи в DirOrganizationBase живут и спокойно себе создаются из формы-примера, который я привел. В чем тогда их абстрактность – я так и не понял.
5. По поводу наследования методов. Дока говорит о том, что «Developers can access the base table method on a derived table buffer. In addition, a derived table method can override a base table method and call super() to invoke the same method on the base table buffer» (Разработчики могут получать доступ к методам на базовой таблице через курсор на производной таблице. В дополнении – метод на производной таблице может перекрыть метод на базовой таблице и вызов super() вызовет метод на базовой таблице).
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Т.е. через курсор производной таблицы доступны методы базовой.
А можно ли их перекрывать? Доступны ли через курсор производной таблицы поля базовой таблицы?
Смотрим скриншот методов базовой и подчиненной таблице и видим по методу addressBooks – что он может быть перекрыт.
Нажмите на изображение для увеличения
Название: overrideMethods.PNG
Просмотров: 185
Размер:	66.8 Кб
ID:	7464
Поля базовой таблицы доступны в производной через this
Нажмите на изображение для увеличения
Название: overrideFields.PNG
Просмотров: 180
Размер:	30.0 Кб
ID:	7465

Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
А тоже самое будет происходить при добавлении таблиц в Query? При создании Query в AOT? При создании Query программно?
Если просто в коде написать "select DirPerson;" будет ли автоматически выбран DirPartyTable?
Из скриншота видно, что будет происходить тоже самое для select.
Нажмите на изображение для увеличения
Название: selectDirPerson.PNG
Просмотров: 245
Размер:	17.6 Кб
ID:	7466
Для Query после того как в АХ 2009 добавили возможность его добавлять на форму - его поведение можно считать такое же как и у формы. Т.е. также будут выбраны все таблицы из иерархии.
Более того, в обозревателе таблиц теперь показывается все. Т.е. как бы на уровне АХ все таблицы, участвующие в иерархии "склеиваются" в одну. И о том, что таблицы все же разные напоминает лишь АОТ, да СУБД.

Цитата:
Сообщение от TasmanianDevil Посмотреть сообщение
Зачем эти лишние вызовы и ожидания? Только для выполнения странной связи по RecId с обоих сторон join'а ? Как скажется на быстродействии вставки и блокировках на SystemSequences подобный многоступенчатый механизм, гарантирующий выполнение уникальности RecId по таблице и равные RecId у связанных записей в таблицах потомков/родителей ?

Половину этих вызовов ( всех возвратов от базовой записи) можно было бы избежать, используя всего лишь еще одно , дополнительное у к уже имеющемуся полю InstanceRelationType, служебное поле-ссылку (какой-нибудь InstanceRelationRecId) в родительских таблицах на запись в таблице-наследнике.
Тогда вставка в самый нижний уровень не ждала бы вставок с верхнего уровня, а все служебные join можно было реализовать как

Select Родитель Left Outer Join
Потомок On Родитель.InstanceRelationType = Потомок.TableId And Родитель.InstanceRelationRecId = Потомок.RecId
.
Согласен с Вами. Но, возможно, такая концепция не вписывалась в понятие наследования.
С другой стороны - если рассуждать с позиции, что иерархия таблиц - суть есть одна большая таблица - то в общем-то один фиг - что вставлять одну большую запись в мегатаблицу, что вставлять много маленьких записей в иерархию. Если все делать в одной транзакции.
Причем, как я понимаю - условие связи 1:1 (1:0), а не 1:N между базовой и производной таблицами никто не отменял. Возможно, поэтому и возник такой непростой механизм вставки записи.

Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Впрочем, не знаю, что это за тип RelationType. Может, в Ax2012 этот тип данных допускает хранение неких списков значений?
Нет. Никаких списков там нет. Я ж говорю - на наследование надо смотреть исходя из гипотезы о том, что это способ вертикального разделения большой мегатаблицы на много маленьких.
__________________
Возможно сделать все. Вопрос времени

Последний раз редактировалось sukhanchik; 12.01.2012 в 23:23.
За это сообщение автора поблагодарили: S.Kuskov (5).
Старый 13.01.2012, 00:00   #7  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,070 / 1800 (67) ++++++++
Регистрация: 12.10.2004
Мы как-то обсуждаем детали.
А по-моему интереснее другой вопрос :
1. Зачем это сделано ?
2. Какие задачи помогает решить проще и дешевле ?
3. Не получим ли мы провал в производительности системы из-за кучи объединенных табличек ?

Выгоды от наследования табличек неочевидны.
Старый 13.01.2012, 02:11   #8  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,202 / 2379 (88) +++++++++
Регистрация: 16.01.2004
Адрес: Москва
Наследнование сущностей существует в любом случае. В Ax2012 сделана поддержка одной из стратегий отображения этого отношения на таблицы БД. Про достоинства и недостатки разных стратегий можно почитать, например, здесь
Старый 13.01.2012, 12:53   #9  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,631 / 2128 (76) +++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Logger Посмотреть сообщение
Мы как-то обсуждаем детали.
А по-моему интереснее другой вопрос :
1. Зачем это сделано ?
2. Какие задачи помогает решить проще и дешевле ?
Судя по АХ 2012 стратегически было принято решение начинать абстрагировать разработчика от СУБД. Если это действительно так - то это ответ на эти вопросы.

Цитата:
Сообщение от Logger Посмотреть сообщение
3. Не получим ли мы провал в производительности системы из-за кучи объединенных табличек ?
Не скажу про производительность на реальном сервере, но могу сказать про собственные наблюдения за виртуалками.
Для компьютера обучающегося, на котором разворачивается виртуалка с АХ 2009 предъявляются (в документах для проведения курса) в том числе такие требования:
  • 2 GB of RAM
  • 60-gigabyte (GB) hard disk
При этом говорится, что сама виртуалка сконфигурирована на 1 Gb.
На деле - если виртуалке дать 2 Гб - то она просто "летает"

Для компьютера обучающегося, на котором разворачивается виртуалка с АХ 2012 предъявляются в том числе такие требования:
  • 8 GB of RAM or higher
  • Dual striped 120 GB hard disks 7200 RM SATA or better
При этом говорится, что сама виртуалка сконфигурирована на 6 Gb.

По факту получается следующее:
Если взять сейлзовую виртуалку (с партнерсорса; она состоит из одного vhd-шника) и поместить ее на выделенный жесткий диск (на котором кроме нее больше вообще ничего нет) и отдать ей 6 Гб памяти то она будет работать неторопливо. А если же на этом диске запустить вторую пустую виртуалку "вхолостую" (только с Win2008 x32) и 1 Гб оперативки - то виртуалка с АХ2012 начинает безбожно тормозить и вешаться. Увеличение оперативки скорости не добавляет. Жесткий диск 2 Тб годичной давности.
Увеличение памяти для виртуалки с АХ 2012 дает плюс только при глобальной компиляции / построении перекрестных ссылок и то больше из-за SQL Server.

Реальный же прирост производительности наблюдается в том случае, когда запускаешь учебную виртуалку (для курсов) на разных дисках. Она состоит из 3-х vhd-шников, 2 из которых являются разностными. Если при этом не трогая последний, 3-й диск - создать чистый 4-й (тоже разностный), и поместить 3-й и 4-й на разный физические диски - то (согласно монитору ресурсов Windows) будет усиленное чтение с 3-го диска и усиленная запись на 4-й (туда будут писаться все изменения).
Увеличение рекомендуемой оперативной памяти для виртуалки особо прироста производительности не дает .
Кстати, перекрестные ссылки на таким образом сконфигурированной учебной виртуалке при отданной ей 12 Гб оперативки строились у меня чуть больше 24 часов. Предварительная глобальная компиляция (иначе построение ссылок вообще уходит в даун) заняла где-то часа 3-4.

Отсюда напрашивается грустный вывод. Производительность АХ 2012 (впрочем, как и ожидалось при нормализации СУБД) упирается не столько в мощности процессора / памяти - сколько в скорость дисков и операций чтения/записи.
__________________
Возможно сделать все. Вопрос времени

Последний раз редактировалось sukhanchik; 13.01.2012 в 13:01.
За это сообщение автора поблагодарили: Logger (5).
Старый 13.01.2012, 13:17   #10  
niksen is offline
niksen
Участник
Самостоятельные клиенты AX
 
284 / 28 (1) +++
Регистрация: 05.07.2011
Адрес: Татарстан
Цитата:
Производительность АХ 2012 (впрочем, как и ожидалось при нормализации СУБД) упирается не столько в мощности процессора / памяти - сколько в скорость дисков и операций чтения/записи.
вывод такой интересный, я конечно не упираюсь в реляционную теорию бд, но при нормализации субд разве всё начинает зависеть от скорости хардов? может я как-то не так логику понимаю, но, допустим ненормализованная бд, в ней 3 таблицы, в каждой из которых допустим 1000 записей по 30 полей в каждом, то есть перебирается 30 000 значений ячеек в сумме 1000 строк, и нормализованная, в которой будет например 15 таблиц, но полей в каждой таблице будет гораздо меньше, то есть перелопачивание данных будет меньше, разве не так?
Старый 13.01.2012, 13:39   #11  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,631 / 2128 (76) +++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от niksen Посмотреть сообщение
вывод такой интересный, я конечно не упираюсь в реляционную теорию бд, но при нормализации субд разве всё начинает зависеть от скорости хардов? может я как-то не так логику понимаю, но, допустим ненормализованная бд, в ней 3 таблицы, в каждой из которых допустим 1000 записей по 30 полей в каждом, то есть перебирается 30 000 значений ячеек в сумме 1000 строк, и нормализованная, в которой будет например 15 таблиц, но полей в каждой таблице будет гораздо меньше, то есть перелопачивание данных будет меньше, разве не так?
"Все - нехорошее слово" (с). При нормализации - скорость хардов заведомо начинает играть бОльшую роль, нежели чем при денормализации.
Причина 1. Когда мы пишем Х++ - обычно мы пишем запрос типа SELECT *, т.е. заведомо выбираем ВСЕ поля - сколько бы их ни было. Т.е. если нам нужно выбрать строку накладной, код клиента и группу клиента, то при денормализации, в которой группа клиентов сидит в накладной - мы не джойним всю таблицу клиентов и производим выборку только всех полей накладной. Если же в накладной нужных нам полей нет, то мы джойним таблицу клиентов и выбираем все поля из этой таблицы - т.е. хотим мы или нет - но выбираем мы больше полей.
В случае разбиения большой таблицы на маленькие - появляются дополнительные поля - связки, которые тоже подлежат выборке.
Причина 2. Индексы. Сколько бы ни было полей в таблице - поиск осуществляется по индексу, а не по Вашему алгоритму (не так часто требуется получить большой набор данных - сколько требуется найти записи, удовлетворяющие некоему критерию отбора).
Причина 3 (следствие). Джойны всегда работают заведомо медленнее, чем выборка из одной таблицы. Плюс LEFT JOIN на порядок тормознутее INNER JOIN.
Причина 4. Данные таблицы можно дефрагментировать внутри файла. А гарантировать, что нужные таблицы при выборке будут находиться рядом друг другом в файле БД - нельзя. Т.е. джойн - это еще дополнительная работа для диска.
__________________
Возможно сделать все. Вопрос времени
Старый 13.01.2012, 13:51   #12  
niksen is offline
niksen
Участник
Самостоятельные клиенты AX
 
284 / 28 (1) +++
Регистрация: 05.07.2011
Адрес: Татарстан
Цитата:
Причина 2. Индексы. Сколько бы ни было полей в таблице - поиск осуществляется по индексу, а не по Вашему алгоритму (не так часто требуется получить большой набор данных - сколько требуется найти записи, удовлетворяющие некоему критерию отбора)
я лишь предположил. То есть как я понимаю Вас, иерархия таблиц сделана не для увеличения скорости, а для удобства и увеличения скорости разработки в целом лишь для отдельных случаев или не так? то есть в общем случае - эта иерархия многим вообще никак не нужна? или наоборот? я просто не очень пойму Вашу позицию
Старый 13.01.2012, 14:42   #13  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,631 / 2128 (76) +++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от niksen Посмотреть сообщение
я лишь предположил. То есть как я понимаю Вас, иерархия таблиц сделана не для увеличения скорости, а для удобства и увеличения скорости разработки в целом лишь для отдельных случаев или не так? то есть в общем случае - эта иерархия многим вообще никак не нужна? или наоборот? я просто не очень пойму Вашу позицию
Моя позиция простая - понять (и дать понять другим) - как это работает, в каких случаях ее лучше применять, в каких случаях ее лучше не применять .

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

Т.е. с моей личной т.з. эта иерархия не стоит тех затрат, которые потратили на ее реализацию. С т.з. структуры СУБД конечно.
Наследование же методов - штука полезная. Другое дело, что вполне возможно - что реализовать наследование методов можно было бы другим путем, не усложняя структуру. Например, убрать методы вообще с таблиц и добавить на таблицу ссылку на класс-обработчик методов на таблице, допустим для простоты строго с тем же названием. А в ядре бы сделать разделение - выборка бы шла по таблице, а обработка методов - по классу. В крайнем случае сделать доп. узел в АОТ что-то типа "Table Handler Classes". В 3.0 ведь создавался узел в Application Documentation и Application Developer Documentation автоматически при создании новой таблицы (даже не только таблицы). Так и тут можно было бы сие также повторить бы.
И тогда бы появился и Class Declaration и классы можно было бы отнаследовать друг от друга.
Конечно - там есть много спорных моментов. Но это по крайней мере не сказалось бы на производительности, а просто не ухудшило бы программирование.

Можно было бы пойти и другим путем - расширить табличные Map-ы, таким образом, что можно было бы наследовать методы от них.

Вполне возможно, что все это обсуждалось и был принят лучший вариант. Жизнь покажет, как это все будет востребовано. Просто на мой взгляд - если в таблице мало записей - то и делить-то ее особенной потребности нет. Ни с т.з. места на диске ни с т.з. повышения производительности. А вот задачу по обеспечению производительности больших таблиц наследование - не решает. Поэтому я пока не вижу ситуаций, когда применение наследования таблиц даст какое-либо преимущество перед одной большой таблицей или просто ручным делением таблиц с доп. полем RefRecID
__________________
Возможно сделать все. Вопрос времени
За это сообщение автора поблагодарили: mazzy (5), Link (2).
Старый 03.03.2013, 10:14   #14  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,631 / 2128 (76) +++++++++
Регистрация: 13.06.2004
Адрес: Москва
Обновил информацию для версии R2 (т.к. там произошли некоторые изменения)
__________________
Возможно сделать все. Вопрос времени
За это сообщение автора поблагодарили: mazzy (5), fed (3), S.Kuskov (10).
Старый 03.03.2013, 10:42   #15  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,309 / 4333 (149) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Очень, очень забавно. Версия 2012 выпускалась под флагом борьбы за нормализацию структур данных. В итоге - после столкновения с реальностью, в версии 2012R2 пришлось денормализовать те же данные до абсурдного состояния. Скрестить companyInfo и DirPartyTable - это уже денормализация за гранью добра и зла...
За это сообщение автора поблагодарили: mazzy (2), Logger (5).
Старый 03.03.2013, 11:49   #16  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,631 / 2128 (76) +++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от fed Посмотреть сообщение
Очень, очень забавно. Версия 2012 выпускалась под флагом борьбы за нормализацию структур данных. В итоге - после столкновения с реальностью, в версии 2012R2 пришлось денормализовать те же данные до абсурдного состояния. Скрестить companyInfo и DirPartyTable - это уже денормализация за гранью добра и зла...
Тут важно не столько "скрещивание" DirPartyTable и CompanyInfo - это в целом - не самое страшное скрещивание. По большому счету - юр лица - это те же контрагенты и к ним применима та же функциональность (в частности, ГАК), что и для клиентов / поставщиков. Правда в CompanyInfo лежало еще ряд полей, которым ну явно нечего делать в DirPartyTable, но я думаю - что это не последнее изменение структуры данных таблиц и постепенно все "растащат" по своим местам.

Важно другое. Фактически - этим изменением на мой взгляд похоронили саму идею иерархии таблиц. Ну т.е. в "теоретических" головах разработчиков ядра системы - можно конечно рисовать иерархию таблиц, а вот на практике, на мой взгляд - никто не будет заморачиваться с этой иерарихей, когда можно тупо создать одну большую мегатаблицу. При этом не придется заморачиваться наследованием методов (раз таблица одна, значит и методы на ней все). Т.е. автоматически исчезает потребность создавать производные таблицы, как средство размещения кода (проще все разместить на одной таблице, нежели себя обманывать и плодить псевдо-таблицу, которой нет в БД).

Но в целом - я рад, что эта идея не прижилась. Уж больно (на мой взгляд) она была искусственной.
__________________
Возможно сделать все. Вопрос времени
За это сообщение автора поблагодарили: mazzy (2).
Старый 03.03.2013, 12:59   #17  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,309 / 4333 (149) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Цитата:
Сообщение от sukhanchik Посмотреть сообщение

Важно другое. Фактически - этим изменением на мой взгляд похоронили саму идею иерархии таблиц. Ну т.е. в "теоретических" головах разработчиков ядра системы - можно конечно рисовать иерархию таблиц, а вот на практике, на мой взгляд - никто не будет заморачиваться с этой иерарихей, когда можно тупо создать одну большую мегатаблицу. При этом не придется заморачиваться наследованием методов (раз таблица одна, значит и методы на ней все). Т.е. автоматически исчезает потребность создавать производные таблицы, как средство размещения кода (проще все разместить на одной таблице, нежели себя обманывать и плодить псевдо-таблицу, которой нет в БД).
Скорее - реализация была безумной. Разумный подход - это когда использование датасорца некоторого уровня иерархии размещает в запросе все датасорцы более высших уровней иерархии, соединенных обычным inner join. Идея, что помещение на форму родительской таблицы также помещает все дочерние с мега-аутер-джойном между ними - что-то из области фантастики. Остается только гадать что употребляли дизайнеры этой фичи - опиаты или каннабиойды...
Ну и конечно, при проектировании прикладной структуры, разработчики должны понимать что каждый дополнительный уровень иерархии таблиц обходится намного дороже чем дополнительный уровень иерархии при проектировании классов. Заводить еще один уровень иерархии из за 1-2-3 аттрибутов - слишком накладно.
За это сообщение автора поблагодарили: sukhanchik (3), S.Kuskov (2).
Старый 03.03.2013, 13:08   #18  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Most Valuable Professional
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
28,843 / 3751 (183) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Цитата:
Сообщение от fed Посмотреть сообщение
...размещает в запросе все датасорцы более высших уровней иерархии, соединенных обычным inner join...
не забывай, что сейчас кроме самой аксапты в одной связке работают: кубы, отчеты, портал, интеграция с офисом и Project Server'ом. А кроме того, есть куча сторонних приложений (например, тот же Retail), которые "общаются с базой аксапты или с самой аксаптой".

Цитата:
Сообщение от fed Посмотреть сообщение
Остается только гадать что употребляли дизайнеры этой фичи - опиаты или каннабиойды...
они просто забыли о других
не стоит привлекать злой умысел, когда достаточно простого бардака
Старый 03.03.2013, 22:22   #19  
db is offline
db
Роман Долгополов (RDOL)
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
 
369 / 419 (14) +++++++
Регистрация: 01.04.2004
Адрес: Москва
Сам, увы, по нормальному с DAX2012 так и не работал, поэтому выскажусь на "общечеловескую" тематику основываясь на предыдущих сообщениях темы.
Чтобы понять что случилось надо рассмотреть возможные варианты отображения иерархий классов в таблицы БД. Применительно к DAX таблица в AOT с полями и методами это "класс", а соответствующая таблица в БД это просто "таблица"

Несомненно наличие механизма отображения иерархий классов в реляционные бд вещь полезная, хоть и не жизненно необходимая
Существуют три общепринятых способа такого отображения
1. Для каждого класса иерархии своя таблица в БД, содержащая только поля данного класса
+ прямолинейное отображение классов в таблицы, нет лишних полей, экономия пространства
- чтобы получить данные конкретного класса нужен join
- при измении структуры классов, перемещении полей надо следом всё это повторять в бд, т.е. физически перемещать поля между таблицами вместе с данными
2. Для каждого конкретного (неабстрактного) класса своя таблица в БД, содержащая все поля как данного класса, так и всех предков
+ Лишнего места (как и первый вариант) не занимает
+ Нет джойнов
- Для построения каких либо отчетов и прочих операциях по промежуточному уровню иерархии появляется union
- Так же как и в случае с первым вариантом изменения структуры классов приводят в необходимости следом изменить структуру таблиц, причем так как поля дублируются во многих таблицах, всё еще гораздо "запущеннее"
- Проблемы с уникальностью ключевых полей. Так как индекс на каждой таблице свой, а constrain-ы привязаны к индексу, весьма вероятны задвоения значений ключевых полей. Т.е. БД перестает даже помогать управлять уникальностью значений и это должно быть реализовано в приложении
3. Для всей иерархии одна таблица в БД, содержащая все поля всех классов иерархии
+ Никаких: join, union, проблем с уникальностью, проблем с поддержкой изменений иерархии
- Не оптимальное расходования места (хотя некоторые бд умеют более умно хранить дефолтные значения столбцов и места пропадает меньше)

Вариант 1 теоретически красив, радует глаз и сердце архитектора и в идеальном объектом мире идеален. Джойны? так СУБД умеет джойнить. Надо тасовать данные при изменении иерархии? А для для чего еще нужны БД, если не для этого. И этот вариант как раз то что появилось в DAX2012. Всё по учебнику, всё красиво и "супер-супер".

Реальный мир, как обычно, практичен и несовершенен. Тучи джойнов напрягают сервера, но не это самое страшное. А вот когда поле передвинули в иерархии и это приводит к необходимости следом переносить столбцы вместе с данными между таблицами, то это уже очень невесело для реальной жизни. Сделать такие изменения "на ходу" даже теоретически непросто и не быстро, не говоря уже о системе 24x7. Дополнительным "увеселителем" ситуации выступают всякие кубы/порталы/репортинг сервисы и прочие примкнувшие приложения, которые мало или вообще ничего не знают о метаданных DAX, а полагаются в основном на ее БД и дружно отказываются работать при изменении ее структуры.

Механизм наследования таблиц сам по себе уж точно не лишнее для DAX. Поэтому решение перейти на 3 вариант, вернув одну широкую таблицу в БД, но оставить все остальное на месте вполне разумный шаг и, по сути, признание своих ошибок. И хотя бы это радует. Учебники, между тем, настоятельно рекомендуют начинать именно с третьего варианта

Последний раз редактировалось db; 03.03.2013 в 22:34.
За это сообщение автора поблагодарили: mazzy (2), gl00mie (3), S.Kuskov (5).
Старый 04.03.2013, 11:43   #20  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,309 / 4333 (149) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Для того чтобы реализация механизма была идеальной, надо было бы просто добавить возможность в свойствах таблицы-наследника указывать место физического хранения ее полей - в отдельной таблице или в той же таблице что и поля родителя.
Теги
ax2012, inheritance, table inheritance, наследование таблиц, полезное

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
emeadaxsupport: New Content for Microsoft Dynamics AX 2012 : October 2011 Blog bot DAX Blogs 0 27.10.2011 17:11
dynamics-ax: Interview with Microsoft's Lachlan Cash on his new role, AX 2012 and more Blog bot DAX Blogs 6 22.04.2011 14:55
axinthefield: Dynamics AX Event IDs Blog bot DAX Blogs 0 01.03.2011 22:11
daxdilip: Whats New in Dynamics AX 2012 (A brief extract from the recently held Tech Conf.) Blog bot DAX Blogs 7 31.01.2011 12:35
dynamics-ax: Modeling the world, with Microsoft Dynamics AX 2012 Blog bot DAX Blogs 0 25.01.2011 09:11
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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