26.02.2016, 19:16 | #1 |
Участник
|
mfp: InventDim in AX7
Источник: http://blogs.msdn.com/b/mfp/archive/...im-in-ax7.aspx
============== Background The way a new inventory dimension is added in AX has not changed significantly for several releases. Even for AX 7 the best guide is still chapter 6 in Inside Dynamics AX 4. In AX 2012 we almost hit a SQL limitation on the maximum number of fields in the DimIdx index (the limit is 16) – preventing you from adding more dimensions. To address this, we added a hashing function in R2 to ensure uniqueness – and a configuration key (InventDimExtensibility) to enable/disable the overhead of hashing. This is described here: Walkthrough: More than 14 InventDim Dimensions Despite Index Limit [AX 2012] and Avoid index length issues with InventDim In AX 2012 R3 the limit is exceeded out of the box. This means that everyone running warehouse was paying the hashing overhead – measured to be about 10% performance degradation. To compensate, we wrote a guide on how to avoid the hashing by disabling other inventory dimensions not needed, like serial numbers or Russian dimensions. This required code changes and thus increased TCO to gain performance. The guide is available here: Microsoft Dynamics AX R3 – New Warehouse Management solutions impact on InventDim extensibility and migration scenarios What changed in AX7? As you can probably see from above, the InventDim story has grown quite complex. In AX7 this stopped. The solution is simpler and faster. Issue 1 – Performance In AX 2012 the hashing value is stored in a container. Container types are relatively expensive is SQL, as they are stored in a column of type varbinary(100). The container type in X++ is also quite expensive, as there is no native IL representation for it. Every reference results in an interop call to the native platform. (aka. Speed of sound). Solution Store the hash in a string instead – hex encoded. 40 characters is enough to contain the hash. String is a native type in IL – much much faster than containers. In SQL the type for the hashing column became nvarchar(40) – also a bit lighter than varbinary(100). Issue 2 – Complexity In AX 2012 R3 you need to consider the max number of fields in an index – if you don't need all the dimensions provided out-of-the-box, you should reshuffle the index to avoid enabling the InventDimExtensibility configuration key. If you truly needed all of the dimensions you paid the performance overhead. Solution Simply just hash all the dimensions. This allows us to deprecated the InventDimExtensibility configuration key. In AX7 all code runs as IL – the price of hashing is insignificant. You no longer need to even consider reshuffling indexes or hashes. In other words, we deleted a bunch of code – and you can focus on more valuable things. Issue 3 – SQL footprint In AX 2012 each dimension was stored 3 times in SQL. One time for the actual column, one time in an index for the dimension, and one time in the big index ensuring uniqueness across dimensions. Solution Given the hash string is enough to guarantee uniqueness, we don't need the big index anymore – we just need a unique index on the hash string. Now, the index guaranteeing uniqueness only contains 3 fields: PartionId, DataAreaId and SHA1HashHex. This reduced the SQL footprint from 2kb to 1.3kb per row – or about 30%. Did it help? Yes, the performance improved significantly. The chart below compares the performance of the InventDim::findOrCreate() method in AX7 before (with InventDimExtensibility ON/OFF) and after this change. Even when always hashing all dimensions we are 40% faster compared to the old system with no hashing. And, you don't have to change the InventDim table again – unless you are adding a new dimension. When adding a new dimension(s) you must:
THIS POST APPLIES TO MICROSOFT DYNAMICS AX7 TECHNICAL PREVIEW; IS PROVIDED AS-IS AND CONFERS NO RIGHTS. ============== Источник: http://blogs.msdn.com/b/mfp/archive/...im-in-ax7.aspx
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору. |
|
|
За это сообщение автора поблагодарили: alex55 (1). |
26.02.2016, 22:46 | #2 |
Участник
|
Вот это поворот!.. Для 2012-й такое штатно наверняка не сделают, но это не беда - можно и самостоятельно такое реализовать. Мне лично другое непонятно: нафига было использовать SHA1 cо 160-битным значением, которое потом пихать в контейнер, контейнер - в varbinary(100), иметь все эти проблемы с производительностью и размером записей таблицы... Ведь можно было использовать MD5 со 128-битным значением, которое прекрасно помещается в родной для SQL тип uniqueidentifier с бинарным представлением "под капотом" и удобным строковым представлением в запросах.
|
|
|
За это сообщение автора поблагодарили: mazzy (2), Logger (5), MikeR (3). |
27.02.2016, 11:19 | #3 |
Участник
|
|
|
27.02.2016, 16:00 | #4 |
Участник
|
Может дело было в скорости генерации значений. Все равно mfp все свел к строкам. Вряд ли они сильно проигрывают гуидам. Ну если только из за объема памяти на хранение.
Хэш функции Why? |
|
27.02.2016, 22:37 | #5 |
Участник
|
Это не так - MD5 быстрее.
GUID - это 16 байт, значения сравниваются бинарно, SHA1 в строковом представлении - это 80 байт (40 символов unicode для hex-представления 160-битного значение), сравнение регистронезависимое, т.е. надо постоянно приводить сравниваемые значения к верхнему или нижнему регистру с учетом collation'а базы данных. |
|
28.02.2016, 09:40 | #6 |
Участник
|
Да, точно, про издержки на сравнение я и забыл.
Ну, аргументов в пользу sha1 не осталось. Кроме меньшей вероятности коллизий. Видимо это и было основным соображением. |
|
28.02.2016, 12:54 | #7 |
Читатель
|
Автор говорит, что 160 бит конвертируются в строку nvarchar(40), длиной 80 байт, т.е. 640 бит, т.е. в ЧЕТЫРЕ раза больше (два символа на байт при конвертации в строковое hex представление, и два байта на символ при хранении в БД). Расточительно, не находите?
|
|
28.02.2016, 17:21 | #8 |
Участник
|
Да, пожалуй расточительно.
|
|
29.02.2016, 09:17 | #9 |
Участник
|
Вообще конечно хотелось бы увидеть, сколько времени метод InventDim::findOrCreate() занимает при разноске какого-нибудь журнала или заказа в процентах. т.е. если это будет число порядка 0.01% от всей времени разноски, то оптимизация конечно мега-важна и необходима
|
|
|
За это сообщение автора поблагодарили: Vadik (1). |
29.02.2016, 11:33 | #10 |
Участник
|
Так запустите разноску с trace parser'ом и скажите нам
|
|
29.02.2016, 12:05 | #11 |
Участник
|
У меня тут совершенно случайно завалялась трассировка разноски на тестовом сервере розничного журнала операций (RetailStatementTable), в ходе которой создается и разносится заказ на продажу:
|
|
|
За это сообщение автора поблагодарили: Ruff (2). |
29.02.2016, 13:34 | #12 |
Участник
|
Спасибо, очень интересно.
Цитата:
total exclusive time - 153 ms - время БД составило 7,4 % ( 10.7 / 153 ) Не маловато ли ? Куда же делось остальное время ? Неужели хеш считался ? (т.е. мы на него потеряли больше 90 % времени вызова InventDim::findOrCreate() ) Последний раз редактировалось Logger; 29.02.2016 в 13:54. |
|
29.02.2016, 14:02 | #13 |
Участник
|
Для приведенных 2205 вызовов InventDim::findOrCreate() было лишь 4 обращения к БД (total database calls), остальные запросы была обработаны из кэша таблицы InventDim на АОСе.
|
|
01.03.2016, 18:43 | #14 |
Участник
|
Автор в комментариях ответил, что использование MD5 в продуктах Microsoft запрещено по соображениям безопасности (алгоритм "взломан" на предмет поиска коллизий), хотя непонятно, какое это отношение имеет к индексированию переменного числа полей в InventDim. В общем, добавить какую-нить #pragma warning для отключения предупреждений компилятора люди могут, а аналогично отключить проверку на использование "небезопаносной" MD5 там, где о криптографии и речи не идет, - видимо, не могут, поэтому и решили мучиться с SHA1, контейнерами, varbinary(100), hex-строками и проч. "Сами создаем себе трудности и сами их героически преодолеваем"
|
|
|
За это сообщение автора поблагодарили: mazzy (2), S.Kuskov (2). |
01.03.2016, 19:55 | #15 |
Участник
|
Цитата:
Вариант 1 SHA1HashHex, dataareaid, partitionid это 80 + 8 + 8 = 96 байт Вариант 2 SHA1HashIntGuid, SHA1HashInt32, dataareaid, partitionid это 16 + 4 + 8 + 8 = 36 байт Выигрыш по объему - 62 % Больше чем в 2,5 раза. |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
02.03.2016, 21:40 | #16 |
Участник
|
на современных процах sha1 уже давно считается быстро
специальные команды же сделали |
|
|
За это сообщение автора поблагодарили: Logger (1). |
03.03.2016, 18:19 | #17 |
Участник
|
есть где развернуться оптимизаторам кода!
__________________
Felix nihil admirari |
|
03.03.2016, 18:58 | #18 |
Участник
|
Не может ли такого быть, что есть какая-то другой сценарий, который требует больше операций с inventdim?
|
|
03.03.2016, 20:46 | #19 |
Участник
|
|
|
03.03.2016, 21:06 | #20 |
Участник
|
|
|
Теги |
ax2012, ax7, hash, inventdim, md5, sha1, ax2012r3 |
|
Похожие темы | ||||
Тема | Ответов | |||
mfp: What is new in X++ in AX7? | 2 | |||
mfp: X++ in AX7: Garbage Collection | 0 | |||
mfp: X++ in AX7: Const keyword | 0 | |||
mfp: X++ in AX7: Static event subscription | 0 | |||
mfp: X++ in AX7 | 0 |
|