02.09.2018, 17:51 | #1 |
Участник
|
Update millions of records
Привет,
Написал скрипты по интеграции нескольких сущностей. Нужно с SQL вытянуть 5 милионов записей и потом обновить их в СРМ Online системе. В общем - сплошная боль, даже с балками перфоманс очень посредственный. Вытянуть за раз 5 тысяч, обновить 1 тысячу, как Вы живете с проектами в которых нужны такие массовые операции? Многопоточность не поможет ибо все запросы становяться в очередь, и все следующие запросы будут ждать выполнения. Как жить в таких условиях? Результаты следующие: - retrieve 5000 = 30 сек, итого только 8,3 часов чтобы вытянуть 5 млн записей - update 1000 = ~2 минуты, итого только 83,33 часов для апдейта - select from SQL by Id 5000 records == 10 минут (слабое место, оптимизирую) Нет плагинов на сущности, + там еще операция назначения. Последний раз редактировалось Ion; 02.09.2018 в 18:07. |
|
02.09.2018, 17:55 | #2 |
Участник
|
Вот такой код, как бы его оптимизировать
X++: public void StartOneByOneProcesssing() { int queryCount = 5000; int pageNumber = 1; int recordCount = 1; Boolean hasRecords = true; PagingInfo pagingInfo = new PagingInfo(); pagingInfo.Count = queryCount; pagingInfo.PageNumber = pageNumber; EntityCollection results = null; var requestWithResults = CreateExecuteMultipleRequest(); Lead sfLead = null; while (hasRecords) { try { // Retrieve the page. swXrm.Start(); results = _xrmLeadService.GetByQueryExpression(GetQueryExpression(queryCount, pageNumber, results?.PagingCookie)); swXrm.Stop(); Console.WriteLine("Elapsed XRM ={0}", swXrm.Elapsed); swXrm.Reset(); hasRecords = results?.Entities?.Count > 0; if (results.Entities != null) { var ids = results.Entities.Select(e => e.GetAttributeValue<string>("new_sfdcid")).ToArray(); swOneBuOnekSql.Start(); var sfLeads = _sfleadService.GetLeads(ids); swOneBuOnekSql.Stop(); Console.WriteLine("Elapsed SQL One By One ={0}", swOneBuOnekSql.Elapsed); swOneBuOnekSql.Reset(); Console.WriteLine("Page cokie = {0}", results?.PagingCookie); swBulkSql.Start(); foreach (var xrmLead in results.Entities) { try { var sfdcid = xrmLead.GetAttributeValue<string>("new_sfdcid"); sfLead = sfLeads.FirstOrDefault(e => e != null && e?.Id == sfdcid); if(sfLead != null) { Entity updatedXrmLead = _leadMapping.Create(xrmLead, sfLead); UpdateRequest update = new UpdateRequest { Target = updatedXrmLead }; requestWithResults.Requests.Add(update); _userService.AssignLead(sfLead, updatedXrmLead.Id, xrmLead.GetAttributeValue<EntityReference>("ownerid")?.Id); } else { _logger.WriteUpdateLog(new UpdateLog("lead", sfLead?.Email ?? xrmLead.GetAttributeValue<string>("emailaddress1"), "not found in sql", sfLead?.Id ?? xrmLead.GetAttributeValue<string>("new_sfdcid"))); } if(requestWithResults.Requests.Count == 1000) { Stopwatch OneThousandRecords = new Stopwatch(); OneThousandRecords.Start(); var responseWithResults = _xrmLeadService.ExecuteMultipleRequest(requestWithResults); OneThousandRecords.Stop(); Console.WriteLine($"1000 processed in {OneThousandRecords.Elapsed}"); //foreach (var responseItem in responseWithResults.Responses) //{ // // An error has occurred. // if (responseItem.Fault != null) // DisplayFault(requestWithResults.Requests[responseItem.RequestIndex], // responseItem.RequestIndex, responseItem.Fault); //} requestWithResults.Requests.Clear(); } } catch (Exception ex) { var sb = ParseError(ex); _logger.WriteErrorLog(new ErrorLog("lead", sfLead?.Email, sb.ToString(), sfLead?.Id)); } } recordCount += queryCount; } swOneBuOnekSql.Stop(); Console.WriteLine($"Fetching page {pageNumber} and total leads processed {recordCount} in {swOneBuOnekSql.Elapsed}"); swOneBuOnekSql.Reset(); pageNumber++; } catch (Exception ex) { hasRecords = false; Console.WriteLine(ex.ToString()); } } Console.WriteLine($"************** One by one processing of leads finished ****************"); } |
|
03.09.2018, 11:08 | #3 |
Участник
|
Проекты, в которых нужны такие массовые операции хромают на обе архитектурные ноги...
|
|
03.09.2018, 12:19 | #4 |
Участник
|
Цитата:
Понятное дело в большенстве случаев такой надобности нет, но в любом случае CRM online имеет очень много 'неудобств' для рядовых разработчиков из-за ограничений Последний раз редактировалось Ion; 03.09.2018 в 12:30. |
|
03.09.2018, 18:01 | #5 |
Участник
|
Косяки одних разработчиков, создающие проблемы другим разработчикам не являются ограничениями системы.
|
|
03.09.2018, 18:25 | #6 |
Участник
|
Цитата:
Как вариант написать майкрософт и попросить их это сделать |
|
03.09.2018, 21:28 | #7 |
Kostya Afendikov
|
Для разовой операции можно использовать дев версию этого продукта https://www.kingswaysoft.com/product...ductivity-pack
Есть возможность менять Batch size да и просто изучите их блог и мануалы, там много инсайдов найдете |
|
03.09.2018, 22:14 | #8 |
Участник
|
Цитата:
Сообщение от Bondonello
Для разовой операции можно использовать дев версию этого продукта https://www.kingswaysoft.com/product...ductivity-pack
Есть возможность менять Batch size да и просто изучите их блог и мануалы, там много инсайдов найдете |
|
04.09.2018, 09:18 | #9 |
Участник
|
Для разовой операции проще использовать SSIS/ У того же KingswaySoft есть компоненты (источники, приемники) для работы с CRM https://www.kingswaysoft.com/product...t-dynamics-365. Для разовых операций компоненты бесплатны. Сам не делал но знаю что в SSIS можно распараллеливать потоки обработки, тем самым можно попытаться снизить время обработки.
|
|
04.09.2018, 18:45 | #10 |
Чайный пьяница
|
Поддержу высказавшихся и буду рекомендовать Kingsway Soft адаптер. На что также рекомендую обратить внимание - "Enable Multithreading" опцию - https://www.kingswaysoft.com/product...rm/destination это должно снизить время на выполнение обновления записи.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit Последний раз редактировалось a33ik; 04.09.2018 в 23:11. |
|
06.09.2018, 09:43 | #11 |
Участник
|
Ребята, спасибо за ссылки, несомненно попробую в следующем проекте, пока оставил как есть т.к. мапинг уже написал и логика готова. На переписать времени не дают)
|
|
06.09.2018, 14:50 | #12 |
Kostya Afendikov
|
Цитата:
update 1000 = ~2 минуты, итого только 83,33 часов для апдейта
|
|
06.09.2018, 17:58 | #13 |
Участник
|
Его и хватило) И все получилось, просто хотелось лучше, быстрее))
|
|
|
|