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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 08.12.2010, 10:14   #1  
Ivanhoe is offline
Ivanhoe
Участник
Аватар для Ivanhoe
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
4,143 / 2155 (80) +++++++++
Регистрация: 29.09.2005
Адрес: Санкт-Петербург
Цитата:
Сообщение от Vadik Посмотреть сообщение
- неспортивно
- неуплаченная "дань за двенадцать лет" (поддержка) зело велика будет
- перевод тройки на 2009 - челлендж покруче любой дефрагментации RecId
1. Ну а что делать Повод просто хороший. Для заинтересованной стороны. С таким объемом на тройке пора бы задуматься о переходе, imho. На 6.0 переходить будет еще сложнее. AX2009 сейчас уже более-менее оттестирована - два SP и кучка RU вышла.
2. Про неуплаченную дань не в курсе, я что-то пропустил? =)
3. Ну, можно вообще дождаться чьего-нибудь пожелания перейти на SAP - мне кажется с т.з. сотрудников поддержки Ax это еще большее зло
__________________
Ivanhoe as is..
Старый 08.12.2010, 11:44   #2  
Vadik is offline
Vadik
Модератор
Аватар для Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3,631 / 1849 (69) ++++++++
Регистрация: 18.11.2002
Адрес: гражданин Москвы
Цитата:
Сообщение от Ivanhoe Посмотреть сообщение
Про неуплаченную дань не в курсе, я что-то пропустил? =)
Я взял на себя смелость предположить что будь в свое время проплачена поддержка, топикстартер в 2010 году на версии 3.0 не сидел бы и сейчас просто взять и получить лицензии на 2009 задешево не получится
__________________
-ТСЯ или -ТЬСЯ ?
Старый 08.12.2010, 10:19   #3  
Alexius is offline
Alexius
Участник
Аватар для Alexius
 
461 / 248 (9) ++++++
Регистрация: 13.12.2001
А нет ли в базе чего-нибудь "лишнего" ? Типа :
1. InventSettlement (Cancelled == true)
2. InventSumLogTTS (не используется сводное планирование)
3. SysDataBaseLog и прочие логи
4. SalesParmTable и подобные *Parm*
5. и т.д.

Может можно почистить базу и облегчить АХ задачу по дефрагментации ?
Старый 08.12.2010, 13:56   #4  
fed is offline
fed
Moderator
Аватар для fed
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,895 / 5650 (194) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Лично однажды забыл поставить RefRecId для одной ссылки. (Хотя я не самый безграмотный и ленивый специалист и про проблему эту знал когда писал. Просто делал в жуткой запаре). Потом мы этим "Надежным и простым" дефрагментатором продефрагментировали. Потом дня через три заметили утрату связи (функциональность не слишком регулярно использовалась). Потом около 2 недель - восстанавливали связь по всяким эвристикам.

Так что вероятность ошибок со ссылками всегда присутствует. А поскольку на работающей системе остановить бизнес на денек-другой и попросить сотрудников потестить - не потрелялось ли что - не реально, предложеный Gustav'ом вариант имеет право на жизнь. Хотя мне тоже кажется что его надо еще доводить и оптимизировать изрядно. Но сама по себе идея интересна и неплоха...

Кстати - тут помниться пару недель назад была дискуссия насчет навешивания ярлыков... Это я к употреблению термина "Кулибин"...
Старый 08.12.2010, 16:04   #5  
Alenka is offline
Alenka
Участник
 
58 / 25 (1) +++
Регистрация: 19.04.2006
Очень понравилась идея от Gustav, т.к. дырок действительно очень много. При "использованных" свыше 3,5 млрд номеров RecId у нас в базе всего около 400 млн записей. И ее еще можно почистить...

Переход на новую версию - это что-то из области фантастики для нашей компании.

Так что вполне вероятно никакой дефрагментации не потребуется.
Старый 08.12.2010, 21:34   #6  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Alenka Посмотреть сообщение
дырок действительно очень много. При "использованных" свыше 3,5 млрд номеров RecId у нас в базе всего около 400 млн записей. И ее еще можно почистить...
У нас похожий процент заполненности, даже еще меньше: на 1.3 млрд RecId - около 100 млн записей.

Я набросал еще один джоб, помогающий понять степень заполненности базы по диапазонам-этапам (stages) размером в 100 млн. номеров RecId.
X++:
static void Job351_CountRecIdsPerStage(Args _args)
{
    // расчет количеств RecId по этапам
    int             i, nLines;
    int             timeFullStart, timeFullFinish;

    Dictionary      dictionary = new Dictionary();
    TableId         tableId;
    DictTable       dictTable;
    Common          common;
    int             row, timeStart;
    int             recordCount;

    int             stage;
    int             stageCnt        = 22;
    int             recIdPerStage   = 100000000;
    int             recIdStart      = 1;
    int             recIdEnd        = recIdPerStage;
    int             recIdCount;

    ;

    timeFullStart = timenow();

    for (stage=1; stage<= stageCnt; stage++)
    {
        recIdCount = 0;
        for (i=1; i<= dictionary.tableCnt(); i++)
        {
            tableId   = dictionary.tableCnt2Id(i);
            dictTable = new DictTable(tableId);

            print strFmt('%1 -- %2 -- %3', stage, tableId, dictTable.name());

            // если в очередной таблице нет записей
            // то переходим к следующей
            try
            {
                nLines = infolog.line();
                recordCount = new SysDictTable(tableId).recordCount();
            }
            catch //может случиться, если таблица есть в репозитарии, но нет в базе
            {
                infolog.clear(nLines);
                recordCount = 0;
            }
            if (! recordCount)
                continue;

            common = dictTable.makeRecord();

            select count(RecId) from common
                where common.RecId >= recIdStart && common.RecId <= recIdEnd;

            recIdCount += common.RecId;
        }

        info(strFmt('%1 -- %2 -- %3 -- %4', stage, recIdStart, recIdEnd, recIdCount));

        if (! recIdCount) 
            break;

        recIdStart      = recIdEnd + 1;
        recIdEnd        = recIdEnd + recIdPerStage;
    }

    timeFullFinish = timenow();
    box::info(strfmt('Total running time: %1 sec', timeFullFinish - timeFullStart));
}
У меня джоб трудился около часа и по окончании выдал следующую информацию (привожу в слегка облагороженном виде):
Код:
stage recIdStart      recIdEnd        recIdCount   % к 100 млн.
---------------------------------------------------------------
 1                1     100 000 000    8 050 727    8%
 2      100 000 001     200 000 000      878 353    1%
 3      200 000 001     300 000 000    1 478 347    1%
 4      300 000 001     400 000 000    1 131 490    1%
 5      400 000 001     500 000 000    2 195 859    2%
 6      500 000 001     600 000 000    1 427 424    1%
 7      600 000 001     700 000 000    1 259 705    1%
 8      700 000 001     800 000 000    2 905 657    3%
 9      800 000 001     900 000 000   16 803 406   17%
10      900 000 001   1 000 000 000   12 565 324   13%
11    1 000 000 001   1 100 000 000   16 741 287   17%
12    1 100 000 001   1 200 000 000   21 317 892   21%
13    1 200 000 001   1 300 000 000   11 187 373   11%
14    1 300 000 001   1 400 000 000            0    0%
---------------------------------------------------------------
                                      97 942 844
Такая вот занятная картина получается. Явная пустота первых 700 млн - полагаю, интенсивная черновая работа на внедрении. Хотя все равно с трудом представляю, как за внедрение можно столько id-шек растратить... Ну и как же тут не захотеть по дыркам повторно пройтись?

Кстати, нашёл у себя аксесный mdb-файл на 28 млн. записей таблицы UsedRecId (см. мой пред. пост). Так вот этот файл имеет размер 1 Gb. Можно использовать это соотношение как оценочное при планировании "завоевания" этапов.

Alenka, а у вас поставщик-внедренец Аксапты - не GMCS ли тоже? У них в приложении масса полезных запросов-отчетов, которые, тем не менее, RecId расходуют нещадно - за счет заполнения вспомогательных таблиц временными данными (не путать с временными таблицами). Т.е. на "совесть" этих запросов-отчетов в нашем приложении половину дыр точно можно списывать...
За это сообщение автора поблагодарили: aidsua (1), G.Menshikh (1).
Старый 08.12.2010, 22:13   #7  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Gustav Посмотреть сообщение
Явная пустота первых 700 млн - полагаю, интенсивная черновая работа на внедрении. Хотя все равно с трудом представляю, как за внедрение можно столько id-шек растратить...
легко. экспорт/импорт с удалением.
__________________
полезное на axForum, github, vk, coub.
Старый 09.12.2010, 10:00   #8  
Alenka is offline
Alenka
Участник
 
58 / 25 (1) +++
Регистрация: 19.04.2006
2 Gustav: внедряли Аксапту нам КОРУС Консалтинг.
Такое кол-во пустот в нумерации действительно возникает из-за таблиц с временными данными, жизнь которых составляет от1 дня до 2 недель. Пустота вначале тоже есть, но она составляет всего около 2 млн.
За это сообщение автора поблагодарили: Gustav (2).
Старый 14.01.2011, 10:03   #9  
Alenka is offline
Alenka
Участник
 
58 / 25 (1) +++
Регистрация: 19.04.2006
Наконец-то нашлось время на испытание, проверку и тестирование идеи с триггером. Выяснилось, что, к сожалению, сама идея заполнения дыр, оставляя в запасе 25 номеров, "не дружит" с insert_recordset. При использовании insert_redordset значение nextVal в SystemSequence передвигается сразу на количество вставляемых записей. Поэтому необходимо держать в запасе в текущей дыре с неиспользованными RecId не 25 номеров, а неограниченное количество, что естественно невозможно.
2 Gustav: Этот случай был просто не учтен Вами или есть какое-то решение?

Последний раз редактировалось Alenka; 14.01.2011 в 10:58.
За это сообщение автора поблагодарили: Vadik (1), Gustav (3), S.Kuskov (1).
Старый 14.01.2011, 12:33   #10  
Alexius is offline
Alexius
Участник
Аватар для Alexius
 
461 / 248 (9) ++++++
Регистрация: 13.12.2001
Цитата:
Сообщение от Alenka Посмотреть сообщение
Такое кол-во пустот в нумерации действительно возникает из-за таблиц с временными данными, жизнь которых составляет от1 дня до 2 недель.
Такие таблицы неплохо бы вытащить в отдельные виртуальные компании.
За это сообщение автора поблагодарили: Vadik (1), Alenka (1).
Старый 17.01.2011, 12:33   #11  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,658 / 1162 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Лично я бы не стал вообще использовать триггера, а делал разовые замены. Логика примерно следующая

1. Создается отдельная таблица "дыр" в нумерации. Причем рассматриваются только большие "дыры" с интервалами не менее, чем тысяч этак 100.
2. Ежедневно запускается пакетник, который анализирует сколько номеров осталось до конца "дыры". Если осталось меньше, чем, скажем, недельный расход RecId, то переключаемся на следующую "дыру".

Разумеется, тут предварительно следует сделать анализ примерного расхода RecId в день и расхода RecId при "глобальных" операциях вроде закрытия склада. Как мне кажется, по InventTrans это будет наглядно видно.

Преимущество данной схемы в том, что вообще ничего и нигде не меняется. Ну, а недостаток в том, что данная схема будет работать только при наличии достаточно больших "дыр" в нумерации. Т.е. таких "дыр", которых хватит хотя бы на неделю работы.
Старый 17.01.2011, 17:30   #12  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Кое-что удалось проверить.

Действительно, insert_recordset генерит значения RecId в количестве, равном количеству записей вставки, начиная со значения nextVal, хранящегося в таблице SystemSequences на момент вызова оператора insert_recordset. После выполнения этого оператора новое значение nextVal = предыдущее значение nextVal + кол-во вставленных записей.

Всё это происходит только в том случае, если у таблицы, в которую вставляются записи, не перекрыт метод insert. Если же перекрыт, то insert_recordset превращается в серию обычных одиночных insert-ов. И это известный факт из курса программирования в Аксапте.

Как показала проверка, стоит нам создать на таблице простейшую версию метода, например, просто используя ту, которая прописывается автоматически:
X++:
public void insert()
{
    super();
}
и ничего больше не делать, как Аксапта начинает при выполнении того же insert_recordset генерить RecId обычными пачками по 25 штук.

Поэтому если есть готовность пожертвовать скоростью вставки, приобретя возможность эффективного использования дыр, то можно просто аналогично перекрыть метод insert() на соответствующей таблице.

У меня во всем приложении Аксапты нашлось всего 12 мест в коде с оператором insert_recordset.

Но это, конечно, выглядит как полумера (хотя лично мне вполне симпатичная) и я продолжаю подумывать о более универсальном подходе. Пока в голову пришло следующее. Использовать для вставок посредством insert_recordset большую непрерывную область за пределами диапазонов, охватываемых таблицей дыр RecId. Тогда каждому вызову insert_recordset будет предшествовать вызов некоего метода, передвигающего nextVal в непрерывную область, а после insert_recordset другой метод будет восстанавливать предыдущее значение nextVal (опять из области дыр). Парными вызовами этих методов (условно назовем их "BEFORE_insert_recordset" и "AFTER_insert_recordset") необходимо будет "окутать" все операторы insert_recordset.
Старый 17.01.2011, 19:07   #13  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,430 / 1772 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Gustav Посмотреть сообщение
Если же перекрыт, то insert_recordset превращается в серию обычных одиночных insert-ов.
Ещё нужно учесть возможность skipDataMethods.
Старый 18.01.2011, 13:54   #14  
Alenka is offline
Alenka
Участник
 
58 / 25 (1) +++
Регистрация: 19.04.2006
У нас во всем приложении было всего 5 вызовов insert_recordset, причем только один из них реально использовался. Его мы заменили на обычный insert.

Хочу поделиться одним по-моему важным замечанием насчет размера кеша. В двухуровневой конфигурации и в трехуровневой с толстым клиентом размер кэша действительно составляет 25 по умолчанию. А вот в трехуровневой с тонким клиентом - 250! Так что при использовании триггера следует рассматривать "дыры" не меньше 250, а не 25, как заявлялось ранее.
Старый 18.01.2011, 16:35   #15  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Обнаружил тему SystemSequences - Выделение RecId, которую, наверное, неплохо иметь в виду при чтении текущей темы.
За это сообщение автора поблагодарили: Alenka (1).
Старый 17.01.2011, 18:47   #16  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
А если рухнет транзакция между переводом в большую область и возвратом взад?

А если конкурентные пользователи начнут хаотично домогаться до строчки с последним номером идентификатора? Блокировки тут будут неприятным, но далеко не самым страшным последствием.
__________________
С уважением,
glibs®
Старый 22.08.2013, 11:52   #17  
abark is offline
abark
Участник
 
14 / 10 (1) +
Регистрация: 26.06.2013
Адрес: Волгоград
Добрый день!

Подскажите пожалуйста, есть ли в Axapta 3.0 возможность переопределить поведение системного класса SystemSequence (по выделению новых recId, работе с внутренним буфером AOS зарезервированных значений recId и тому подобное)?

Цель в том, чтобы иметь более гибкий контроль механизма выделения, чтобы был доступен более широкий контекст, нежели это позволяет способ через sql триггер на таблице SYSTEMSEQUENCES.
Старый 22.08.2013, 12:04   #18  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от abark Посмотреть сообщение
Цель в том, чтобы иметь более гибкий контроль механизма выделения, чтобы был доступен более широкий контекст, нежели это позволяет способ через sql триггер на таблице SYSTEMSEQUENCES.
Не нужно так делать. Ни в коем случае.
там зарыто столько скелетов... прежде всего с кэшированием таблиц и работой в кластере АОСов.
я уверен, что никакой "более гибкий" не может перекрыть затрат на борьбу со скелетами.

Если у вас всегда один АОС,
Если у вас никогда не используется кэширование таблиц,
Если у вас никогда не будет виртуальных компаний,
Если у вас никогда не будет доменов и т.п.
То подумать на тему "переопределить" можно.

Если хоть что-то и перечисленного есть - дешевле будет перейти на следующую версию Аксапты.
За это сообщение автора поблагодарили: abark (1).
Старый 22.08.2013, 13:09   #19  
abark is offline
abark
Участник
 
14 / 10 (1) +
Регистрация: 26.06.2013
Адрес: Волгоград
Цитата:
Сообщение от mazzy Посмотреть сообщение
Если у вас всегда один АОС,
Если у вас никогда не используется кэширование таблиц,
Если у вас никогда не будет виртуальных компаний,
Если у вас никогда не будет доменов и т.п.
То подумать на тему "переопределить" можно.
АОСов несколько,
кеширование (если речь идет про свойство CacheLookup у таблиц) очевидно применяется где-то, например в стандартном функционале, и его отключать не хочется
виртуальная компания есть (vrt)
домены есть


Цитата:
Сообщение от mazzy Посмотреть сообщение
Не нужно так делать. Ни в коем случае.
там зарыто столько скелетов... прежде всего с кэшированием таблиц и работой в кластере АОСов.
я уверен, что никакой "более гибкий" не может перекрыть затрат на борьбу со скелетами.

...

Если хоть что-то и перечисленного есть - дешевле будет перейти на следующую версию Аксапты.
Хм, понятно что все непросто.
Ситуация такая что на достаточно большой базе (1,7 Тб, 4.5 лет) приближается нулевое значение recId. Поэтому ищется как раз решение подешевле. Пока выбирается между: 1) дефрагментацией, 2) реализацией механизма заполнения дырок, хотя очевидно также потребуется 3) чистка старых InventTrans (сильно не тривиальная задача), ну или 4) переезд в новую базу с остатками. Пока реализация механизма заполнения дырок видится самой легкой из вышеперечисленного. Вариант перехода на следующую версию Ax пока не рассматривается.

Но встает вопрос про некоторую "ассинхронность" выделения блока новых recId между AOS и SQL. Так триггер на SQL отрабатывая еще не знает какой в будущем непрерывный блок идентификаторов попросит у него AOS, и поэтому алогритмически не может точно выбрать самую подходящую дырку. Остается только реализовывать какие-то эмпирические подходы, ну или в случае попыток выделения чрезмерных блоков обрывать такие попытки через reaiseerror в триггере. При этом Ах-код очевидно может свалиться в самых произвольных местах, и тут остается верить что код достаточно покрыт транзакциями, и/или быть готовым к неожиданностям.
Вот поэтому хотелось бы как-то в триггере (или в другом месте - переопределении класса SystemSequence?) в момент резервирования очередного непрерывного блока сразу выдавать ему самую подходящую по размерам дырку.
Старый 22.08.2013, 13:12   #20  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
если еще не делали дефрагментарию на акс3.0, то сначала сделайте ее.
Теги
ax3.0, recid, дефрагментирование recid, законченный пример, полезное

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
if (record) vs if (record.RecId) kashperuk DAX: Программирование 18 27.11.2008 18:53
поля, содержащие RecId somebody DAX: Программирование 15 16.05.2008 17:50
Что лучше select RecId или select TableId Logger DAX: Программирование 9 02.06.2007 15:13
aEremenko: Дефрагментация RecID Blog bot DAX Blogs 2 06.03.2007 22:25
Два RecId у одной записи таблицы sparur DAX: Программирование 33 18.12.2006 15:56

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

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

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