12.01.2021, 14:33 | #1 |
Участник
|
Выгрузка измененных клиентов во внешнюю систему
Стоит такая задача - есть внешняя система, ей как-то надо передавать клиентов из АХ которые изменились за интервал времени.
Клиентов много(около 6млн) Интервал хотят около минуты, т.е. раз в минуту идет запрос к АХ - дай мне клиентов(из определенной группы), которые изменились за последнюю минуту. Полей для отслеживания немного, Код клиента, Имя, Адрес, Мобильный телефон, Почта. Проблема что все они разбросаны по разным таблицам Решал ли кто-нибудь такую задачу и как решали? Версия АХ2012 |
|
12.01.2021, 15:06 | #2 |
Banned
|
|
|
|
За это сообщение автора поблагодарили: Vadik (1), trud (2). |
12.01.2021, 15:22 | #3 |
Модератор
|
"Из коробки" есть поддержка change tracking в AIF, но .getChangedKeys() пожалуй слишком "тяжело" реализован чтобы его раз в минуту вызывать, тем более на таких объемах, плюс чувствителен к рассинхронизации времени на вызывающей стороне и в AX.
У "интервал хотят около минуты" требования есть какие-то разумные обоснования ?
__________________
-ТСЯ или -ТЬСЯ ? |
|
12.01.2021, 15:24 | #4 |
Участник
|
Спасибо. Я правда не очень понимаю, как это будет работать,
1 - change tracking он же включится для всей таблицы, получается будет много пустых срабатываний(когда поменялись не нужные нам поля)? 2 - плюс по связям - для примера LOGISTICSELECTRONICADDRESS напрямую с клиентом не связана(связана через несколько таблиц). что в этом случае будет трекаться 3 - как делать горизонтальную фильтрацию, т.е. мне нужны клиенты которые менялись из заданной группы, причем группа может быть разной. Описанный способ после запроса просто помечает весь запрос как использованный |
|
12.01.2021, 15:32 | #5 |
Участник
|
Почему не создать табличку нужных данных/добавить нужные поля в существующую раз полей немного, с modify date time и обновлением данных при изменении первичных данных?
|
|
12.01.2021, 15:35 | #6 |
Модератор
|
да
Цитата:
плюс по связям - для примера LOGISTICSELECTRONICADDRESS напрямую с клиентом не связана(связана через несколько таблиц). что в этом случае будет трекаться
Цитата:
как делать горизонтальную фильтрацию, т.е. мне нужны клиенты которые менялись из заданной группы, причем группа может быть разной
__________________
-ТСЯ или -ТЬСЯ ? Последний раз редактировалось Vadik; 12.01.2021 в 15:42. |
|
12.01.2021, 15:41 | #7 |
Участник
|
Пока пытаюсь понять направление. В этом как раз и загвоздка, как делать такое обновление. Могу ошибаться, но припоминаю проблемы типа что при изменении LOGISTICSELECTRONICADDRESS (именно в момент вставки), связи с клиентом там еще не будет, т.е. DIRPARTYLOCATION создастся позже, т.е. надо именно искать место в классах где это меняется, что трудоемко.
|
|
12.01.2021, 15:42 | #8 |
Модератор
|
вот тут CT достаточно подробно обсуждалось
__________________
-ТСЯ или -ТЬСЯ ? Последний раз редактировалось Vadik; 12.01.2021 в 16:03. |
|
|
За это сообщение автора поблагодарили: trud (3). |
12.01.2021, 16:13 | #9 |
Участник
|
Цитата:
Клиент уже пробовал реализовать это включением даты модификации на каждой таблице, и запросом где дата модификации фильтруется по ИЛИ для каждой таблицы. Это работает, но медленно, т.е. запрос выполняется больше чем минуту, а таких приходит по десятку в минуту для разных групп Еще вопрос с ченж трекингом - он живет несколько дней, как быть если они захотят обновить данные полностью (к примеру получить клиентов за последние несколько лет)? писать отдельную обработку? Пример запроса который они сделали X++: .. INNER JOIN LOGISTICSELECTRONICADDRESS leaEmail ON dplEmail.LOCATION = leaEmail.LOCATION AND leaEmail.TYPE = 2 -- Email AND (leaEmail.VALIDFROM <= @sync_new_received_anchor AND leaEmail.VALIDTO > @sync_new_received_anchor) LEFT OUTER join DIRNAMEAFFIX dna ON dna.RECID = dp.PERSONALTITLE AND dna.AFFIXTYPE = 1 LEFT OUTER JOIN ( SELECT dpl.PARTY as PARTY, lea.LOCATOR as LOCATOR, ll.MODIFIEDDATETIME as LL_MODIFIEDDATETIME, lea.MODIFIEDDATETIME as LEA_MODIFIEDDATETIME FROM DIRPARTYLOCATION dpl INNER JOIN LOGISTICSLOCATION ll ON ll.RECID = dpl.LOCATION AND ll.DESCRIPTION = 'Home' -- Home phone number INNER JOIN LOGISTICSELECTRONICADDRESS lea ON lea.LOCATION = dpl.LOCATION AND lea.TYPE = 1 -- Phone AND (lea.VALIDFROM <= @sync_new_received_anchor AND lea.VALIDTO > @sync_new_received_anchor) WHERE (dpl.VALIDFROM <= @sync_new_received_anchor AND dpl.VALIDTO > @sync_new_received_anchor) ) homePhone ON homePhone.PARTY = dp.RECID LEFT OUTER JOIN ( SELECT dpl.PARTY as PARTY, lea.LOCATOR as LOCATOR, ll.MODIFIEDDATETIME as LL_MODIFIEDDATETIME, lea.MODIFIEDDATETIME as LEA_MODIFIEDDATETIME FROM DIRPARTYLOCATION dpl INNER JOIN LOGISTICSLOCATION ll ON ll.RECID = dpl.LOCATION AND ll.DESCRIPTION = 'Mobile' -- Mobile phone number INNER JOIN LOGISTICSELECTRONICADDRESS lea ON lea.LOCATION = dpl.LOCATION AND lea.TYPE = 1 -- Phone AND (lea.VALIDFROM <= @sync_new_received_anchor AND lea.VALIDTO > @sync_new_received_anchor) WHERE (dpl.VALIDFROM <= @sync_new_received_anchor AND dpl.VALIDTO > @sync_new_received_anchor) ) mobilePhone ON mobilePhone.PARTY = dp.RECID WHERE c.DATAAREAID = @AXDataAreaId AND c.OWIGUID != '00000000-0000-0000-0000-000000000000' AND c.ONETIMECUSTOMER = 0 -- Don't sync one time customers AND c.CUSTGROUP = @custGroup AND ( (c.MODIFIEDDATETIME >= @sync_last_received_anchor AND c.MODIFIEDDATETIME < @sync_new_received_anchor) OR (dpn.MODIFIEDDATETIME >= @sync_last_received_anchor AND dpn.MODIFIEDDATETIME < @sync_new_received_anchor) OR (leaEmail.MODIFIEDDATETIME >= @sync_last_received_anchor AND leaEmail.MODIFIEDDATETIME < @sync_new_received_anchor) OR (dna.MODIFIEDDATETIME >= @sync_last_received_anchor AND dna.MODIFIEDDATETIME < @sync_new_received_anchor) OR (homePhone.LEA_MODIFIEDDATETIME >= @sync_last_received_anchor AND homePhone.LEA_MODIFIEDDATETIME < @sync_new_received_anchor) OR (homePhone.LL_MODIFIEDDATETIME >= @sync_last_received_anchor AND homePhone.LL_MODIFIEDDATETIME < @sync_new_received_anchor) OR (mobilePhone.LEA_MODIFIEDDATETIME >= @sync_last_received_anchor AND mobilePhone.LEA_MODIFIEDDATETIME < @sync_new_received_anchor) OR (mobilePhone.LL_MODIFIEDDATETIME >= @sync_last_received_anchor AND mobilePhone.LL_MODIFIEDDATETIME < @sync_new_received_anchor) ) |
|
12.01.2021, 16:27 | #10 |
Moderator
|
Мне всегда казалось, что для таких задач не modifieddatetime используется, а modifiedTransactionId. По нему проще индекс построить да и highmark тоже проще хранить.
Плюс я бы попробовал логику сбора изменений слегка изменить. Сначала я бы завел временную таблицу с CustAccount. Потом написал бы запрос по custTable->DirpartyTable->LogisticsPostalAddress (в общем - я точную последовательность не помню, но в общем развернул бы полную цепочку), в последнюю таблицу добавил бы условие modifiedTransactionId>highMark. Результаты сложил бы во временную табличку. Потом аналогичный запрос, но уже более простой custTable->DirpartyTable к последней табличке опять бы добавил условие ModifiedTransactionId>highMark. В итоге - после того как каждый уровень запроса опрошен на предмет наличия изменений, сделал бы обычный джойн со всеми данными, но в этот джойн добавил бы exists join ко временной таблице. Ну и чтобы не тормозило - по всем табличкам добавил бы индекс modifiedTransactionId+joinField. Каждый отдельный запрос относительно простой и можно в случае чего индексов достроить. Ну и в итоге - запрос обычного набора данных для уже отобранных 10-15 годовых клиентских кодов вполне можно быстро прочитать. |
|
12.01.2021, 16:42 | #11 |
Участник
|
Да, это кстати тоже идея - разбить этот большой запрос на подзапросы и потом все объединить, получается на первый взгляд проще чем с созданием лога или ченж трекинга
|
|
12.01.2021, 18:12 | #12 |
Модератор
|
Цитата:
Цитата:
Еще вопрос с ченж трекингом - он живет несколько дней, как быть если они захотят обновить данные полностью (к примеру получить клиентов за последние несколько лет)? писать отдельную обработку?
__________________
-ТСЯ или -ТЬСЯ ? |
|
12.01.2021, 18:27 | #13 |
Участник
|
ну требования просты - есть функция(хранимая процедура) которая принимает группу клиентов, и интервал. надо вернуть все данные которые менялись в этом интервале.
в нормальном режиме будут запускать раз в минуту по группе(т.е. в минуту будет даже больше запусков, несколько десятков)-это хотелось бы сделать быстро. но ничего не мешает запустить произвольный интервал, например за год Тут еще в процессе обдумывания возникло понимание что дату модификации вообще использовать неправильно, она может принадлежать прошлому периоду, если у нас большая транзакция. т.е. процесс должен иметь несколько стадий, первая стадия помечает запись как измененную. Вторая стадия должна как-то этому изменению присваивать дату(можно наверное заложиться что транзакция точно закомитится в пределах секунды) и присваивать дату как текущую плюс 1 секунда Что-то получается все не просто Последний раз редактировалось trud; 12.01.2021 в 18:53. |
|
12.01.2021, 18:41 | #14 |
Участник
|
Цитата:
Сообщение от Vadik
AIF в runtime генерит запрос который из CT вытаскивает изменения по каждой таблице в Query, их по relations "пристыковывает" к "главной" таблице и объединяет все через UNION. Т.е. одному клиенту поменяли группу, второму отчество, третьему адрес а четвертому - мобильный, но getChangedKeys() увидит и вернет все четыре AxdCustomer документа как измененные.
Будет ли эта штука(с пристыковываниями) работать с таблицей которая присоединена по outer join(при том что таких таблиц несколько в одном запросе)? Последний раз редактировалось trud; 12.01.2021 в 18:43. |
|
12.01.2021, 19:08 | #15 |
Модератор
|
Цитата:
Цитата:
А вот этот момент можешь раскрыть подробнее? т.е. в исходном запросе будут outer join для всяких адресов, емейлов и прочего.
Будет ли эта штука(с пристыковываниями) работать с таблицей которая присоединена по outer join(при том что таких таблиц несколько в одном запросе)?
__________________
-ТСЯ или -ТЬСЯ ? |
|
12.01.2021, 20:26 | #16 |
Модератор
|
Цитата:
Сообщение от trud
ну требования просты - есть функция(хранимая процедура) которая принимает группу клиентов, и интервал. надо вернуть все данные которые менялись в этом интервале.
в нормальном режиме будут запускать раз в минуту по группе(т.е. в минуту будет даже больше запусков, несколько десятков)
__________________
-ТСЯ или -ТЬСЯ ? Последний раз редактировалось Vadik; 12.01.2021 в 20:37. |
|
12.01.2021, 23:45 | #17 |
Участник
|
Цитата:
Если да то можно сделать пакетник который бегает по измененным с прошлого прохода записям LOGISTICSELECTRONICADDRESS скидывая изменения в соответствующую табличку. |
|
13.01.2021, 00:33 | #18 |
Участник
|
Цитата:
Цитата:
Гонять запросы "а что там поменялось в 6М клиентов" между двумя системами чуть ли не ежесекундно - не понимаю кому и зачем это нужно
для этого каждая из них днем когда работают люди дергает хранимую процедуру(дай мне измененные данные за последнюю минуту), как правило они возвращают пусто или 1-2 записи Цитата:
Да, понимаю что звучит как черная магия но - будет.
|
|
13.01.2021, 08:24 | #19 |
Участник
|
Цитата:
Параметр - время запуска При запуске процесса выбираем все измененные записи от параметра до текущего момента (ессно при включенном modified time). Далее после обработки сохраняем в параметре текущее время. Обработку табличек можно распараллелить: не думаю что в таблицах идет какой то вал массовых изменений. Последний раз редактировалось axm2017; 13.01.2021 в 08:28. |
|
13.01.2021, 12:49 | #20 |
Модератор
|
Цитата:
Сообщение от trud
Ну вроде требование логичное, я так понимаю вторая система - это система в конкретном офисе(локальный веб сайт), когда тебе меняют что-то в АХ, изменения должны как можно скорее отобразиться в этой системе. Для этого каждая из них днем когда работают люди дергает хранимую процедуру(дай мне измененные данные за последнюю минуту), как правило они возвращают пусто или 1-2 записи
Не думаю что непрерывно вхолостую дрючить источник (AX) запросами с сайта десятки раз в минуту это оптимальное решение. Как мне кажется, логичнее было бы перехватывать изменения в самом источнике и выталкивать сообщения в очередь (AIF outbound queue, MQ, Service Bus, еще что-то) Из спортивного интереса, я бы позадавал вопросы о том сколько клиентов обновляется в час / сутки (средние и пиковые значения), и что ужасного может произойти если изменения опубликуются скажем в среднем в течение получаса (опрашиваем CT раз в час)
__________________
-ТСЯ или -ТЬСЯ ? Последний раз редактировалось Vadik; 14.01.2021 в 10:53. |
|
Теги |
aif, ax2012, change tracking, интеграция, как правильно |
|
|