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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 13.01.2021, 13:48   #21  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
А если просто в журнале базы данных SysDatabaseLog искать все записи за последнюю минуту, у которых нужный TableId ?
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 13:57   #22  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Я как-то делал отчет, который из журнала базы данных достает историю изменения выбранных полей. Вроде довольно быстро работает на базе в 500 Гб. Правда там журнал базы данных хранился только за последние 2 недели, а потом обрезался.
А вам всего-то надо узнать какие записи изменились из списка нужных вам таблиц.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 14:29   #23  
Vadik is offline
Vadik
Модератор
Аватар для Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3,586 / 1757 (66) ++++++++
Регистрация: 18.11.2002
Адрес: гражданин Москвы
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
Я как-то делал отчет, который из журнала базы данных достает историю изменения выбранных полей. Вроде довольно быстро работает на базе в 500 Гб
"Довольно быстро", или "достаточно быстро чтобы непрерывно делать это 10+ раз в минуту", учитывая других читателей-писателей в лог ?
__________________
-ТСЯ или -ТЬСЯ ?

Последний раз редактировалось Vadik; 13.01.2021 в 14:53.
Старый 13.01.2021, 14:52   #24  
Pustik is offline
Pustik
Участник
 
805 / 364 (14) ++++++
Регистрация: 04.06.2004
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
Правда там журнал базы данных хранился только за последние 2 недели, а потом обрезался.
А вам всего-то надо узнать какие записи изменились из списка нужных вам таблиц.
Там еще хотят запускать за определенные периоды :
Цитата:
Сообщение от trud Посмотреть сообщение
в нормальном режиме будут запускать раз в минуту по группе(т.е. в минуту будет даже больше запусков, несколько десятков)-это хотелось бы сделать быстро. но ничего не мешает запустить произвольный интервал, например за год
т.е. лог придется хранить для этих таблиц как минимум год. Но идея хорошая если лог небольшой и скорость будет приемлемая.Опять таки надо пробовать.
На худой конец можно создать свой лог-таблицу под эту задачу.
У нас практикуется репликация о которой говорил axm2017.
Цитата:
Сообщение от axm2017 Посмотреть сообщение
Типичное ( во всяком случае видел реализации подобной идеи на пакете)

Параметр - время запуска

При запуске процесса выбираем все измененные записи от параметра до текущего момента (ессно при включенном modified time).

Далее после обработки сохраняем в параметре текущее время.
правда без ограничения на изменение определенных полей и без такого чуда как LOGISTICSELECTRONICADDRESS(слава богу).Работает массово и стабильно уже много лет в пакетах.

Цитата:
Сообщение от Vadik Посмотреть сообщение
"Довольно быстро", или "достаточно быстро чтобы непрерывно делать это 10+ раз в минуту", учитывая других читателей-писателей в лог ?
Если под эту задачу сделать свою таблицу, да с толковыми индексами, то будет очень быстро работать.
__________________
-Ты в гномиков веришь?
-Нет.
-А они в тебя верят, смотри, не подведи их.

Последний раз редактировалось Pustik; 13.01.2021 в 15:00.
Старый 13.01.2021, 15:19   #25  
trud is offline
trud
Участник
Лучший по профессии 2017
 
988 / 1401 (48) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от axm2017 Посмотреть сообщение
Типичное ( во всяком случае видел реализации подобной идеи на пакете)

Параметр - время запуска

При запуске процесса выбираем все измененные записи от параметра до текущего момента (ессно при включенном modified time).

Далее после обработки сохраняем в параметре текущее время.
Так же не будет работать. Ну т.е. у вас началась транзакция, клиент обновился, далее она к примеру идет час, и только после этого вы увидите вашего клиента(у него будет время обновления час назад). Если ваш пакетник будет запускаться чаще - вы его просто не увидите, так как время в пакете уйдет вперед
Старый 13.01.2021, 15:37   #26  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Цитата:
Сообщение от Vadik Посмотреть сообщение
"Довольно быстро", или "достаточно быстро чтобы непрерывно делать это 10+ раз в минуту", учитывая других читателей-писателей в лог ?
Я делал отчет, который парсил контейнер, чтобы достать значения конкретных полей. И еще надо поймать момент изменения именно нужного поля среди прочего мусора. Поэтому основное время уходило на этот парсинг.
А запрос к таблице SysDatabaseLog вроде быстро выполнялся. Прошло уже несколько лет с того времени. По-любому надо пробовать. По-моему это самый простой способ решить данную проблему. А начинать пробовать надо с простых способов.
Хотя все-таки поймать изменение конкретного поля через таблицу SysDatabaseLog - задача не очень тривиальная, но пример как это сделать есть. Даже на этом форуме выкладывали.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 15:37   #27  
axm2017 is offline
axm2017
Участник
 
517 / 199 (8) ++++++
Регистрация: 15.05.2017
Цитата:
Сообщение от trud Посмотреть сообщение
Так же не будет работать.
Задайте период x -1 час или -1 день раз такие длинные по времени транзакции из общих соображений количество изменений для данных таблиц все одно невелико.
Можно и в лог измененных записей поиграть конечно.
.

Последний раз редактировалось axm2017; 13.01.2021 в 15:40.
Старый 13.01.2021, 15:39   #28  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Запустил у себя сейчас такой джоб.
Для 26 тысяч клиентов он отработал примерно за 2 минуты (если убрать вывод в инфолог)
Это для Аксапты версии 3.0

X++:
static void sysDatabaseLogFieldChangedCustAxForum(Args _args)
{
    CustTable                    custTable;
    SysDatabaseLog               SysDatabaseLog;

    int                          i;
    container                    tmp;

    SysOperationProgress         sysOperationProgress = new SysOperationProgress(1);
    int                          stepCount;
    int                          total;
    UserInfo                    UserInfo;

;
    select count(RecId) from custTable;
    total = custTable.RecId;

    sysOperationProgress.setTotal(total);

    while select custTable
    {
        stepCount ++;
        sysOperationProgress.setCount(stepCount);
        sysOperationProgress.setText(strFmt("%1 запись из %2", stepCount, total));

        while select SysDatabaseLog order by createdDate, createdTime
            where SysDatabaseLog.LogRecId == custTable.RecId
              &&  SysDatabaseLog.table    == custTable.TableId
        {
            if (typeOf(conpeek(SysDatabaseLog.Data, 1)) == Types::Container)
            {
                for ( i = 1; i <= conlen(SysDatabaseLog.data); i ++)
                {
                    tmp = conpeek(SysDatabaseLog.Data, i );
                    if (fieldExt2Id(conpeek(tmp, 1)) == fieldnum(custTable, zResponsibleDivision))
                    {
                        if(conpeek(tmp, 3) != conpeek(tmp, 2))
                        {
                            select firstonly UserInfo where UserInfo.Id == SysDatabaseLog.createdBy;
                            info(strfmt("%1 ~ %2 ~ %3 ~ %4 ~ %5", custTable.AccountNum, UserInfo.name,  SysDatabaseLog.createdDate, conpeek(tmp, 3),conpeek(tmp, 2) ));
                        }
                    }
                }
            }
        }
    }
}
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/

Последний раз редактировалось Ace of Database; 13.01.2021 в 15:41.
Старый 13.01.2021, 15:43   #29  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Т.е. 26000 вызовов select для таблицы SysDatabaseLog срабатывают за 2 минуты и плюс еще время на парсинг
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 15:48   #30  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
В таблице SysDatabaseLog сейчас 74 миллиона записей. Похоже, что ее перестали обрезать
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 15:55   #31  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Автор топика может для своих нужд переписать джоб так, чтобы он отправил всего один запрос к SysDatabaseLog вместо 26 тысяч запросов, но тогда придется усложнить парсинг, чтобы сохранять предыдущие значения полей для каждой записи. Все-таки у него 6 миллионов клиентов, а не 26 тысяч. Но в выборку у него попадут не более нескольких сотен записей, т.к. ему нужны изменения только за последнюю минуту.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 16:29   #32  
trud is offline
trud
Участник
Лучший по профессии 2017
 
988 / 1401 (48) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Там главная проблема в том что связи сложны. Ну т.е. я там выше привел пример запроса который они сейчас используют. (Выгрузка измененных клиентов во внешнюю систему)
Т.е. понятно что для одной таблицы это все сделать просто. С outer join у вас будет 8 вариантов в различных комбинациях. Если делать с интервалом несколько часов(чтобы покрыть длинные транзакции) то данных будет много
Старый 13.01.2021, 16:38   #33  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
А если вот так сделать?
А потом уже сопоставлять отобранные записи вручную между собой через всякие Map'ы ?

X++:
while select SysDatabaseLog order by createdDate, createdTime
            where 
                SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS)
{
}
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 16:45   #34  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Вот так запихнуть всю историю в мапы, а потом мапы сопоставляеть между собой

X++:
Map mapCustTable = new Map(Types::String, Types::Container),
Map mapDIRPARTYLOCATION = new Map(Types::String, Types::Container),
Map mapLOGISTICSELECTRONICADDRESS = new Map(Types::String, Types::Container),

while select SysDatabaseLog order by createdDate, createdTime
            where 
                SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS)
{
    switch(SysDatabaseLog.table)
    {
        case tableNum(custTable):
            mapCustTable.insert(strfmt("%1_%2_%3", SysDatabaseLog.LogRecId, SysDatabaseLog.CreatedDate, SysDatabaseLog.CreatedTime), SysDatabaseLog.data);
            break;
    }
}
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 16:50   #35  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Т.е. у вас будет 8 мапов.
Например, если в мапе mapLOGISTICSELECTRONICADDRESS изменилось нужное вам поле, то вы уже можете обычным для Аксапты способом через таблицу LOGISTICSELECTRONICADDRESS выйти на того клиента, и узнать его код. И даже сопоставлять между собой эти 8 мапов не надо.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 13.01.2021, 17:10   #36  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Вот как-то так:
X++:
    LogisticsElectronicAddress logisticsElectronicAddress;
    MapEnumerator me = new MapEnumerator(mapLogisticsElectronicAddress);
    CustTable custTable;
    RefRecId refRecId;
    while (me && me.moveNext())
    {
        refRecId = str2Int64(conPeek(str2Con_RU(me.currentKey(), "_"), 1));
        logisticsElectronicAddress = LogisticsElectronicAddress::findRecId(refRecId);
        custTable = CustTable::findByPartyRecId(logisticsElectronicAddress .PrivateForParty);
    }
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/

Последний раз редактировалось Ace of Database; 13.01.2021 в 17:13.
Старый 13.01.2021, 18:53   #37  
trud is offline
trud
Участник
Лучший по профессии 2017
 
988 / 1401 (48) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
что-то я потерял идею
X++:
while select SysDatabaseLog order by createdDate, createdTime
            where 
                SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS)
Будут же какие-то другие условия? Если это дата - то какой интервал брать?
Старый 13.01.2021, 20:45   #38  
Ace of Database is offline
Ace of Database
Участник
Аватар для Ace of Database
 
839 / 581 (21) +++++++
Регистрация: 14.10.2004
Это пример был из АХ3. Там дата и время создания записи хранятся в отдельных полях
А для АХ 2012, чтобы вернуть все изменения за последнюю минуту, можно написать так:
X++:
    while select SysDatabaseLog order by createdDateTime
        where SysDatabaseLog.createdDateTime >= DateTimeUtil::addMinutes(DateTimeUtil::utcNow(), -1)
        && (SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS))
    {
    }
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/
Старый 14.01.2021, 01:53   #39  
trud is offline
trud
Участник
Лучший по профессии 2017
 
988 / 1401 (48) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от Ace of Database Посмотреть сообщение
А для АХ 2012, чтобы вернуть все изменения за последнюю минуту, можно написать так:
X++:
    while select SysDatabaseLog order by createdDateTime
        where SysDatabaseLog.createdDateTime >= DateTimeUtil::addMinutes(DateTimeUtil::utcNow(), -1)
Ну это будут изменения за последнюю минуту по которым завершилась транзакция в момент запуска данного запроса. Также могут быть изменения за конкретно эту же минуту по которым транзакция еще не завершилась, они появятся позже, как она завершится. Как предлагаете их искать?
Старый 14.01.2021, 08:18   #40  
Pustik is offline
Pustik
Участник
 
805 / 364 (14) ++++++
Регистрация: 04.06.2004
Цитата:
Сообщение от trud Посмотреть сообщение
Ну это будут изменения за последнюю минуту по которым завершилась транзакция в момент запуска данного запроса. Также могут быть изменения за конкретно эту же минуту по которым транзакция еще не завершилась, они появятся позже, как она завершится. Как предлагаете их искать?
можно сохранять время запуска последней репликации в отдельной выделенной для этого табличке как у нас, т.е принцип такой :

1) запоминаем время запуска текущей репликации startDateTime = DateTimeUtil::utcNow()
2) достаем из таблички дату-время запуска последней репликации = lastDateTime
3) пошла репликация:
X++:
while select SysDatabaseLog order by createdDateTime
        where SysDatabaseLog.createdDateTime >= lastDateTime
        && (SysDatabaseLog.table    == tableNum(custTable)
            ||  SysDatabaseLog.table    == tableNum(DIRPARTYLOCATION)
            ||  SysDatabaseLog.table    == tableNum(LOGISTICSELECTRONICADDRESS))
    {
    }
4) сохраняем в табличке дату-время запуска текущей репликации startDateTime

PS: А меняя в этой табличке дату-время запуска последней репликации можно управлять интервалом минута, месяц, год и т.д.
__________________
-Ты в гномиков веришь?
-Нет.
-А они в тебя верят, смотри, не подведи их.

Последний раз редактировалось Pustik; 14.01.2021 в 08:26.
Теги
aif, ax2012, change tracking, интеграция, как правильно

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
AX2012 Общие справочники поставщиков и клиентов PTG DAX: Функционал 2 11.06.2015 15:39
Импорт адресов для существующих клиентов и поставщиков IKA DAX: Программирование 0 10.12.2013 21:04
ax 3.0 Экспорт справочников во внешнюю систему, по какому ключу связаться? Shakr DAX: Программирование 2 11.11.2008 11:34
Сергей Герасимов: О технической поддержке клиентов по продуктам Microsoft Dynamics Blog bot DAX Blogs 4 13.02.2007 14:58
Коды клиентов в CRM - проблема Zabr DAX: Функционал 5 01.12.2003 12:41
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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