0. Eleepod 37 11.02.19 10:40 Сейчас в теме

Обработка элементов ссылочных типов порциями

Небольшое дополнение к рекомендации от 1С по оптимизации использования оперативной памяти (https://its.1c.ru/db/v8std#content:2149184374:hdoc).

Перейти к публикации

Комментарии
Избранное Подписка Сортировка: Древо
1. A_Max 16 11.02.19 14:55 Сейчас в теме
Это конечно хорошо, но ВНЕЗАПНО может появиться объект с УИД меньше последнего обработанного.
Почему:
1. Никто вам не обещал и гарантирет того, что уиды генерируются последовательно.
2. Обмены

Поэтому и создаются регистры сведений ОчередьХХХХХХХХ
dsdred; Irwin; +2 Ответить
2. triviumfan 10 11.02.19 18:11 Сейчас в теме
(1) такие вещи делают в монопольном режиме имхо
Plotks2017; +1 1 Ответить
7. lunjio 60 11.02.19 20:53 Сейчас в теме
(1) Речь просто о необходимости порционно обрабатывать информацию, в случае что вы описываете, есть ещё необходимость последовательности, ну хорошо, в этом случае используем МоментВремени() ссылки и вопрос решен. Регистры же, как правило создают для отложенной обработки, в статье же в первом предложении говорится, что порционно при неограниченно больших данных.
8. Eleepod 37 12.02.19 00:27 Сейчас в теме
(1)Согласен, в случае если во время обработки в системе могут появится новые данные они могут быть не обработаны. Данный вариант стоит рассматривать как альтернативу запросу, который получает все данные за одну выборку.
dsdred; Plotks2017; +2 Ответить
23. markers 226 14.02.19 04:51 Сейчас в теме
(8) А что изменится если запросить сразу все? При запросе всей информации данный риск даже выше. И данный способ настолько прост и от этого хорош! При этом не надо добавлять реквизиты и пр.
11. Darklight 17 12.02.19 13:15 Сейчас в теме
(1)Просто так такие UID не появляются. У них есть стандарт генерирования (у 1С он свой UUID, у мелкомягких свой - GUID) - и он хронологический. Вариантов появления младших UID только два:
1. Обмен данных с другой системой, формирующих UID на другом компьютере, выполненный параллельно с обработкой
2. UID задаётся вручную строкой не по тем же правилам его формирования - опять таки каким-то параллельным процессом

Для данного примера вероятен только п.1. (п.2. почти невероятен - но кто его знает, что там пишу криворукие программисты на местах)
Поэтому, можно на время обработки остановить обмен. Это вообще важное замечание для ряда подобных обработок - ведь появление пропущенной ссылки тут не самое страшное, что может произойти, когда в данные вклинится параллельный процесс.
Ну или, хотя бы блокировку данных надо наложить (увы - в данном примере - на всю таблицу)!

Да, кстати, замечу, что если вообще не заморачиваться - и выбрать все Ссылки разом а потом их обрабатывать - то это так же ни гарантирует, что в процессе обработки не появятся новые Ссылки (в любой "хронологии"), которые останутся не обработанными - проблема не повторяемого чтения (или наоборот - будут удалены - проблема фантомов). Вот для этого и существуют блокировки данных!
Ali1976; dsdred; Krio2; acanta; +4 Ответить
3. lemz 75 11.02.19 18:32 Сейчас в теме
Хочется убивать конечно уже за использование запроса в цикле. Ограничение выборки хотя бы по ссылке имеет здравое зерно
6. lunjio 60 11.02.19 19:38 Сейчас в теме
(3) Запросы в цикле не всегда зло, есть таблица 10 гб размером, сервак просто помирает при попытке выбрать из нее, как сделать как ни порционно и в цикле ? Убивать хочется за тупую архитектуру и кривую логику, когда люди вместо того чтобы попытаться найти фунционал или взять удачный пример из типовых или других решений, придумывают велосипеды, да причем очень кустарные.
Артано; Plotks2017; +2 Ответить
10. Shmell 240 12.02.19 11:29 Сейчас в теме
(3) такой подход очень оправдан. При этом у Вас не засоряется кэш объектов вследствии использования ПолучитьОбъект(), и немаловажный момент - что Вы можете параллелить обработку порций объектов разными фоновыми заданиями.
Plotks2017; +1 Ответить
14. Darklight 17 12.02.19 13:28 Сейчас в теме
(3)Не понимаю к чему Вы так предрались. Запросы в цикле - это не есть абсолютное зло, особенно когда это цикли порционной обработки. При работе с Big Data так вообще без этого НИКАК не обойтись!

Вот создавать каждый раз запрос в цикле - не очень красиво, но для данного примера - абсолютно не критично!
Plotks2017; for_sale; +2 Ответить
4. acanta 48 11.02.19 18:35 Сейчас в теме
То есть сравнение на больше меньше работает по Гуиду как по строке?
for_sale; +1 Ответить
9. Eleepod 37 12.02.19 01:11 Сейчас в теме
(4) Примерно, но только не в том представлении как оно выводится методом УникальныйИдентификатор. Например ГУИД dee6e178-55bc-11d9-848a-00112f435cbd при ошибке "объект не найден" будет выведен как 848a00112f435cbd11d955bcdee6e178, т.е. вид A-B-C-D-E превращается в DECBA. Думаю в таком виде они и сравниваются.
18. kuzyara 678 13.02.19 07:41 Сейчас в теме
(9) гуиды имеют тип binary(16) и сравниваются побитово как бинарные данные: binary bit-for-bit comparison behavior
Функция ПолучитьGUIDПоУникальномуИдентификатору(UUID1)
    UUID=ВРЕГ(UUID1);
    ч1 = Сред(UUID,20,4);
    ч2 = Сред(UUID,25,12);
    ч3 = Сред(UUID,15,4);
    ч4 = Сред(UUID,10,4);
    ч5 = Сред(UUID,1,8);
    Возврат "0x" + ч1 + ч2 + ч3 + ч4 + ч5;
КонецФункции
Показать

А если кто-то как Darklight думает что гуиды формируются хронологически - почитайте статью Как формируется GUID?

Гуиды выдаются пулом по 32 штуки для каждого сеанса отдельно, за исключением random based uuid получаемых через Новый УникальныйИдентификатор()
5. lunjio 60 11.02.19 19:36 Сейчас в теме
Боже мой, уже весь мир давно использует, посмотрите процедуры корректировки стоимости списания в УПП, ПЕРВЫЕ 3000 ГДЕ &ПоследнийОбъектОчереди = НЕОПРЕДЕЛЕНО ИЛИ Объект.Ссылка > &ПоследнийОбъектОчереди УПОРЯДОЧИТЬ ПО Объект.Ссылка.
dsdred; Irwin; Shmell; +3 Ответить
12. Darklight 17 12.02.19 13:18 Сейчас в теме
(5)Думаю не весь мир. Решение очевидно понятное (если ссылки сортируются, значит они могут сравниваться), да неприглядное ;-) не привычно вот таки воспринимать ссылки большинству!
13. Darklight 17 12.02.19 13:25 Сейчас в теме

в данном случае нельзя сортировать данные по другим полям, кроме ссылки, так что если нужно обрабатывать данные в определенной последовательности, то такой метод не подойдет.

Зачем так людей пугаете. Конечно же можно - если поля сортировки будут ниже поля упорядочивания по ссылеке - то никаких проблем (но это бывает редко - когда ссылка это и есть ключевой обрабатываемый объект)
А вот, если поля для сортировки стоят раньше ссылки - то тогда их так же придётся включить в контроллируемые (по классическому подходу) - и пример несколько усложнится, потеряв своё изначальное изящество - но будет работать. Хоршо бы и такой пример привести тоже.



Так же следует учитывать, что сортировка по ссылке не означает сортировку по моменту времени.

Если речь про момент времени документов - то да, Ссылка <> МоментВремени - но там как раз Ссылку лучше заменить на МоментВремени - он так же уникален (и не повторяем) как и Ссылка.
Если же имелся в виду какой-то другой момент времени - то надо уточнить - какой и в чём проблема!
17. Eleepod 37 12.02.19 22:45 Сейчас в теме
(13) Похоже про сортировку я действительно не прав. А насчет ссылок и моментов времени хотел предостеречь от заблуждения что сортировка по ссылке равна сортировке по моменту времени. Уберу пока эти моменты. Спасибо за комментарии!
15. lunjio 60 12.02.19 13:37 Сейчас в теме
Единственный трындец, который может наступить, это допустим когда мы не прямую таблицу типа обрабатываем, допустим справочника номенклатуры или документа, а какой-нибудь регистр сведений и за такое поле принимаем измерение у которого может пустая ссылка в измерении и таких ссылок больше, чем обрабатываемая порция, вот тогда да, конец света )
16. Darklight 17 12.02.19 17:57 Сейчас в теме
(15)У Вас пример, немного из другой оперы, хотя автор в теме статьи не ограничил её только обработкой источников, являющихся только объектными (аля справочников и документов). Да, там где обрабатываемый объект не является ключевым (как ссылка) для выборки - эта техника не сгодится. Но ничего особо сложного - делаете структуру со свойствами - где все ключевые измерения и сохраняеете текующую позицию туда. В запросе по ним всем сортируете, а условие будет на "ИЛИ" по этим измерениям (и так же на ">"), а в цикле обновляете их все из данных выборки в структуре через ЗаполнитьЗначенияСвойств - как -то так - вроде ничего особенного - код сложнее где-то на (10 + количество ключевых полей) процентов.
19. Glebis 11 13.02.19 09:29 Сейчас в теме
Предлагаю ещё немного рефакторинга:
 	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ ПЕРВЫЕ 1000
	|	Номенклатура.Ссылка КАК Ссылка,
	|	Номенклатура.Наименование КАК Наименование,
	|	Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|ГДЕ
	|	Номенклатура.Ссылка > &ПоследняяСсылка
	|	И <условие выборки необработанных записей>
	|
	|УПОРЯДОЧИТЬ ПО
	|	Ссылка";
	Запрос.УстановитьПараметр("ПоследняяСсылка", Справочники.Номенклатура.ПустаяСсылка());
	РезультатЗапроса = Запрос.Выполнить();
	Пока НЕ РезультатЗапроса.Пустой() Цикл
		// Обход порции результата запроса
		ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
		Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
			// Обработка элемента выборки
			// ...
		КонецЦикла;
		Запрос.УстановитьПараметр("ПоследняяСсылка", ВыборкаДетальныеЗаписи.Ссылка);
		РезультатЗапроса = Запрос.Выполнить();
	КонецЦикла;
Показать
20. Glebis 11 13.02.19 09:43 Сейчас в теме
Если есть проблема с новыми ссылками, то почему бы не складывать уже обработанные в массив и проверять вхождение при обработки каждой порции?

Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ ПЕРВЫЕ 1000
	|	Номенклатура.Ссылка КАК Ссылка,
	|	Номенклатура.Наименование КАК Наименование,
	|	Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|ГДЕ
	|	НЕ Номенклатура.Ссылка В (&МассивОбработанныхСсылок)
	|	И <условие выборки необработанных записей";
	МассивОбработанныхСсылок = Новый Массив;
	Запрос.УстановитьПараметр("МассивОбработанныхСсылок", МассивОбработанныхСсылок);
	РезультатЗапроса = Запрос.Выполнить();
	Пока НЕ РезультатЗапроса.Пустой() Цикл
		// Обход порции результата запроса
		ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
		Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
			МассивОбработанныхСсылок.Добавить(ВыборкаДетальныеЗаписи.Ссылка);
			// Обработка элемента выборки
			// ...
		КонецЦикла;
		Запрос.УстановитьПараметр("МассивОбработанныхСсылок", МассивОбработанныхСсылок);
		РезультатЗапроса = Запрос.Выполнить();
	КонецЦикла;
Показать
21. Glebis 11 13.02.19 11:03 Сейчас в теме
Если предыдущий вариант со складированием ссылок обработанных объектов в массив не подходит, то можно попробовать ещё один особо извращенский способ: переделать запрос на НЕ вхождение порции в таблицу изменений справочника. Но здесь имеются подводные камни, которые нужно проверять: наложение общей транзакции, отдельный план обмена с ручной регистрацией и ещё куча других вопросов.
22. VmvLer 13.02.19 14:23 Сейчас в теме
если немного подумать то АВТОНОМЕРЗАПИСИ() решает задачу разбиения выборки на порции

размер порции 1000, 10 000,... задаем параметром и дальше простая математика в SQL без шаманских пассов получает порционную выборку
24. user970589 14.02.19 10:05 Сейчас в теме
Картинка зачотная!!! пацсталом. ссылочные элементы. порциями. аххах..
25. dsdred 987 17.02.19 08:40 Сейчас в теме
Старый способ...
уже описывал в статье https://infostart.ru/public/893304/

А вообще способ "декоративный" - не надежный!
Не дураки придумали ПланОбмена и номера сообщений - этот вариант тоже показан в статье https://infostart.ru/public/893304/
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Программист 1С
Санкт-Петербург
зарплата от 135 000 руб. до 135 000 руб.
Полный день

Программист 1С
Норильск
зарплата от 50 000 руб. до 80 000 руб.
Полный день

Специалист техподдержки 1С
Иркутск
зарплата от 28 000 руб. до 34 000 руб.
Полный день

Программист 1С
Санкт-Петербург
зарплата от 48 000 руб. до 96 000 руб.
По совместительству

Программист 1С
Ставрополь
зарплата от 40 000 руб. до 60 000 руб.
Полный день