Имя: Пароль:
1C
1С v8
Конвертация 2.1 как выгружать записи регистра сведений порциями?
, , ,
0 il0
 
13.11.17
13:48
Есть конвертация 2.1, в ней настроена выгрузка из ЕРП в Розницу, в том числе и регистра сведений НоменклатураСегментов. У нас так получается, что периодически объем изменений в этом регистре достигает нескольких сотен тысяч записей, соответственно, при загрузке в розницу одним пакетом это все грузится часами, если не сутками. И пока не загрузится, следующие изменения в розницу не попадают, что неприемлемо.
Решил ограничить объём выгружаемых за один раз записей, в ПКО РС НоменклатураСегментов, в процедуре ПередВыгрузкой если счётчик превышает порог пишу Отказ=Истина.
Прикол в том, что, оказывается, записи РС выгружаются не сами по себе, а в составе набора записей. Т.е. выгружается узел с набором записей, а в этом наборе находится одна запись. Там, где отрабатывает Отказ=Истина, узел с набором записей всё равно создается, просто не пишется вложенный узел с самой записью. Почему так, мне не понятно. Из-за этого при обратной синхронизации из розницы регистрация изменений снимается всё равно со всех записей, и выгруженных и не выгруженных.
Есть идеи, как по другому выгружать записи РС порциями?
Сорри за многобукв.
1 Zhuravlik
 
13.11.17
13:50
Используется штатная выборка?
2 il0
 
13.11.17
13:54
(1) Нет, изменения регистрируются программно при изменении элемента справочника СегментыНоменклатуры
3 Zhuravlik
 
13.11.17
14:02
(2) Я о правилах) ПВД как работает? Штатно все выбирается, не запросом? Можно поизвращаться с запросом, в общем, но тогда квитирование ляжет на плечи разработчика
4 il0
 
13.11.17
14:07
(3) ПВД работает по стандартной выборке. Пожалуй, поковыряю вариант с запросом.
5 тарам пам пам
 
13.11.17
14:12
(0) Погугли еще флажок "основной отбор" в измерении регистра НоменклатураСегмента - он на регистрацию влияет. Скорее всего, на номенклатуре он снят - в этом случае как раз регистрируется и выгружается весь регистр одним набором. Если его поставить, то регистр будет регистрироваться и выгружаться по одной записи, в разрезе каждой номенклатуры.
6 тарам пам пам
 
13.11.17
14:14
(5)+ по крайней мере, так он для РИБ работает. По идее, конвертация тоже должна его учитывать.
7 il0
 
13.11.17
14:25
(5) У регистра три измерения - Сегмент, Номенклатура, Характеристика, и у всех стоит флаг "основной отбор". Не знал, что это может влиять на характер выгрузки. У меня как раз на каждую запись создаётся по отдельному набору. Т.е. 700000 записей - 700000 наборов
8 тарам пам пам
 
13.11.17
14:31
(7) хм, выходит в конвертации он не учитывается. А почему изменений так много? Номенклатура действительно постоянно "плавает" между сегментами?
9 Zhuravlik
 
13.11.17
14:58
(7) может имеет смысл попробовать его снять с какого-нибудь измерения, чтобы наборы выгружать  по 2, а не по трем
10 il0
 
13.11.17
15:04
(8) Отдел маркетинга таким образом скидки назначает, здесь довольно запутанный механизм ценообразования, пока не вникал, можно ли это по-другому организовать. Думал с технической стороны проблему по-быстрому решу, а в результате зарылся что-то.
11 тарам пам пам
 
13.11.17
15:38
(10) если в лоб - можно действительно попробовать снять этот флаг с номенклатуры и характеристик, как в (9) предложили, чтобы сегменты выгружались целиком. Обычно целый набор пишется гораздо быстрее кучи мелких записей. Но тогда к обмену будет регистрироваться по сути всегда весь сегмент, даже если в нем изменили только одну позицию номенклатуры.
12 kudlach
 
13.11.17
15:49
Они сегмент обработкой что ли присваивают в таких количествах ?
Это же как Планы обмена с регистрацией то перегружаются....
И база уже в Террабайтах меряется...
13 il0
 
14.11.17
13:08
В общем, коллеги, итог суточных изысканий: по наводке уважаемого Zhuravlik сначала игрался с ПВД, и на первый взгляд даже получилось. Код в обработчике ПередВыгрузкой

Если Параметры.СчетчикНоменклатурыСегментов>2 Тогда
    Отказ=Истина;
Иначе
    Параметры.СчетчикНоменклатурыСегментов=Параметры.СчетчикНоменклатурыСегментов+1;
КонецЕсли;

действительно выгружал только 3 записи. Но проблема оказалась в том, что выгруженными считались всё равно все записи регистра, и при обратном ответе от розницы регистрация изменений снималась со всех записей, а не только с трёх реально выгруженных.
Аналогичная история произошла и с обработчиком ПередОбработкой, в нем я пытался выбирать измененные записи и запросом к таблице РегистрСведений.НоменклатураСегмента.Изменения, и с помощью ПланыОбмена.ВыбратьИзменения(Узел,1,Метаданные.РегистрыСведений.НоменклатураСегмента) но в этих случаях всё равно выгрузка продолжала считать все записи выгруженными, а не только реально обработанную часть.
14 il0
 
14.11.17
13:23
(13) Продолжаю.
В итоге решил отказаться от использования ПВД, отключил его, чтобы оно не "портило" информацию о выгруженности записей. В самой конвертации в обработчике ПослеВыгрузкиДанных вставил следующий код:
Узел=ПланыОбмена.ОбменУправлениеПредприятиемРозница.НайтиПоНаименованию("Розница, редакция 2.1 (2)");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 3
|    НоменклатураСегментаИзменения.Сегмент,
|    НоменклатураСегментаИзменения.Номенклатура,
|    НоменклатураСегментаИзменения.Характеристика
|ИЗ
|    РегистрСведений.НоменклатураСегмента.Изменения КАК НоменклатураСегментаИзменения
|ГДЕ
|    НоменклатураСегментаИзменения.Узел = &Узел";

Запрос.УстановитьПараметр("Узел",Узел);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаТ=РезультатЗапроса.Выбрать();
НаборЗаписей=РегистрыСведений.НоменклатураСегмента.СоздатьНаборЗаписей();
Пока ВыборкаТ.Следующий() Цикл
    НаборЗаписей.Отбор.Сегмент.Установить(ВыборкаТ.Сегмент,Истина);
    НаборЗаписей.Отбор.Номенклатура.Установить(ВыборкаТ.Номенклатура,Истина);
    НаборЗаписей.Отбор.Характеристика.Установить(ВыборкаТ.Характеристика,Истина);
    НаборЗаписей.Прочитать();
    ВыгрузитьРегистр(НаборЗаписей, , , Истина, "НоменклатураСегмента"); // создаем узел с записью
    Выборка=ПланыОбмена.ВыбратьИзменения(Узел,Узел.НомерОтправленного,НаборЗаписей); // регистрируем запись как отправленную в обмен
КонецЦикла;

И оно заработало. Обратите внимание на две вещи:
1) Для выгрузки записей регистра сведений нельзя пользоваться процедурой ВыгрузитьПоПравилу - она тупо создает узел с записью регистра, а такой узел не понимает процедура загрузки, и дает ошибку. Процедура ВыгрузитьРегистр создает корректный узел с набором записей, содержащий коллекцию строк из одной строки
2) Оказывается, в качестве фильтра для метода ВыбратьИзменения можно использовать не только метаданные, но, в случае с регистром сведений, и набор записей. Тогда метод возвращает только те записи которые есть в переданном наборе, и ТОЛЬКО ДЛЯ НИХ проставляет номер отправленного сообщения.

Т.о. я в ручном режиме выполняю то, что делает ПВД, но только в той части, в которой мне надо.
15 il0
 
14.11.17
17:37
Ещё поправка - в запросе сначала нужно выбирать ранее выгруженные изменения, чтобы повторно их выгружать, чтобы они не терялись, если не загрузились в предыдущие итерации

Запрос.Текст =
        "ВЫБРАТЬ ПЕРВЫЕ 10000
        |    НоменклатураСегментаИзменения.Сегмент,
        |    НоменклатураСегментаИзменения.Номенклатура,
        |    НоменклатураСегментаИзменения.Характеристика,
        |    НоменклатураСегментаИзменения.НомерСообщения
        |ИЗ
        |    РегистрСведений.НоменклатураСегмента.Изменения КАК НоменклатураСегментаИзменения
        |ГДЕ
        |    НоменклатураСегментаИзменения.Узел = &Узел
        |
        |УПОРЯДОЧИТЬ ПО
        |    НоменклатураСегментаИзменения.НомерСообщения УБЫВ";
Выдавать глобальные идеи — это удовольствие; искать сволочные маленькие ошибки — вот настоящая работа. Фредерик Брукс-младший