Удаление массива записей в независимом регистре сведений?

1. SanchoD 316 25.12.23 10:44 Сейчас в теме
Приветствую, коллеги!

Столкнулся с такой проблемой. Есть регистр сведений, где свыше 50 млн. записей. В нем 2 измерения. Нужно удалить записи, где одно из измерений находится в массиве порядка 1000 элементов.
Делаю перебор массива, устанавливаю отбор для набора записей равный выбранному элементу и записываю набор.
Таким образом реализую что и требуется. Но достаточно медленно.
Можно ли каким-то альтернативным путем удалить записи регистра?
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. RustamZz 25.12.23 10:58 Сейчас в теме
(1) Сколько записей надо удалить и сколько оставить?
5. SanchoD 316 25.12.23 11:31 Сейчас в теме
(2) Несколько тысяч записей удалить, остаться должны около 50 млн.
10. RustamZz 25.12.23 11:52 Сейчас в теме
(5) Можно дождаться 25 релиза кстати он уже появился в тестовом режиме
11. SanchoD 316 25.12.23 12:04 Сейчас в теме
(10) Да, здорово что они это реализовали. Жалко что не скоро, скорее всего, выйдет продуктовая версия платформы.
4. spacecraft 25.12.23 11:24 Сейчас в теме
(1) Сформировать все наборы не записывая и поместить в массив. Затем в одной транзакции в цикле записать.
7. SanchoD 316 25.12.23 11:32 Сейчас в теме
(4) Спасибо за идею, попробую.
16. SanchoD 316 25.12.23 14:37 Сейчас в теме
(4) Такой вариант дал прирост быстродействия в 22%. По старому алгоритму уходило 45 секунд на одну марку, по новому 35 секунд. Это лучше чем было, но не существенно ускоряет процесс. 1000 элементов будет обрабатываться не 12,5 часов, а 10.
18. spacecraft 25.12.23 14:46 Сейчас в теме
(16) замеры как производились? Если в отладчике, то это не замеры производительности алгоритма, а замеры работы отладчика.
Ну и чуда тоже ожидать не следует.
6. glek 120 25.12.23 11:31 Сейчас в теме
(1) Как указал (3), загрузить в набор таблицу и записать. А таблицу выгрести запросом. И не надо каждый раз перебирать.
12. booksfill 25.12.23 12:13 Сейчас в теме
(1)
1000


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

Если удаляемых записей много рекомендуется потом пересобрать статистику.
13. Sashares 35 25.12.23 12:14 Сейчас в теме
14. SanchoD 316 25.12.23 12:17 Сейчас в теме
(13)
МассивМарок = Докум.АкцизныеМарки.ВыгрузитьКолонку("АкцизнаяМарка");
	Для xxx=0 По МассивМарок.ВГраница() Цикл
		НЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьНаборЗаписей();
		НЗ.Отбор.АкцизнаяМарка.Установить(МассивМарок[xxx]);
		Если ЗаписатьОбъект(НЗ) Тогда
			Сообщить("Очищена запись в РС по марке: " + МассивМарок[xxx]);
		КонецЕсли;
	КонецЦикла;
15. Sashares 35 25.12.23 12:27 Сейчас в теме
(14)Только если поместить цикл в транзакцию, может быть будет чуть быстрее.
3. romulanin 25.12.23 11:16 Сейчас в теме
В теории

НаборЗаписей = РегистрыСведений.Регистр.СоздатьНаборЗаписей();
НаборЗаписей.Загрузить(ТабЗначений);
НаборЗаписей.Записать();
8. SanchoD 316 25.12.23 11:36 Сейчас в теме
(3) ТабЗначений это полученные записи регистра с отбором Измерение1 В(МассивЭлементов)? Тогда остануться только они, а удалятся все остальные. Или ТабЗначений это 50 млн. записей без нескольких тысяч?
Ну это верная смерть для процесса.
9. VmvLer 25.12.23 11:38 Сейчас в теме
(6) если использовать код в (3), то сначала платформа будет "обнулять" таблицу из около 50КК записей, а потом записывать записи в количестве ТабЗначений.Количество()

Не упадет, на современных платформах все ок с такими объемами?
17. SanchoD 316 25.12.23 14:44 Сейчас в теме
А еще смущает то, что интерактивно можно выделить 1000 записей в форме списка регистра и удалит их за 3 минуты.
Почему?
19. spacecraft 25.12.23 15:14 Сейчас в теме
(17) что именно "Почему"?
Долго или быстро?
Предположу, что измерение не первое и не указано "Индексировать".
Основное время тратится на поиск записей.
20. SanchoD 316 25.12.23 15:55 Сейчас в теме
(19) Быстро. Потому что те же 1000 записей очистить через набор записей часов десять займет.
21. spacecraft 25.12.23 16:24 Сейчас в теме
(20) так логично. При выборе записей в форме списка эти записи уже имеются и их не нужно искать.
При
НЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьНаборЗаписей();
НЗ.Отбор.АкцизнаяМарка.Установить(МассивМарок[xxx]);

устанавливается отбор по значению неиндексируемого измерения. Чтобы найти нужные записи в 50млн записях потребуется очень много времени. Вот основное время и тратится на этот поиск.
22. spacecraft 25.12.23 16:30 Сейчас в теме
(20) а вот нужно удалить именно только по АкцизнаяМарка?
Если устанавливать еще и первое измерение в отбор, то будет использоваться кластерный индекс и время поиска сократится на порядки.
24. SanchoD 316 25.12.23 16:55 Сейчас в теме
(22) Первое измерение неизвестно. Но на самом деле практически все время обработки тратиться на запись набора.
25. Sashares 35 25.12.23 16:57 Сейчас в теме
(24)
Первое измерение неизвестно.

Выбрать первые 1000
измерение1
измерение2,
где измерение2 в (&МассивМарок)

В цикле удалять полученные записи и выполнять запрос снова.
Пока запрос не перестанет возвращать записи.
26. spacecraft 25.12.23 17:05 Сейчас в теме
(24)
Но на самом деле практически все время обработки тратиться на запись набора.

Поиск выполняется под капотом. Чтобы удалить конкретные записи их сначала нужно найти.
23. Sashares 35 25.12.23 16:41 Сейчас в теме
(17)На самом деле задача решается и через форму списка.
Добавьте в форму списка отбор по этим 1000 значениям измерения.
Потом контрл +А - делет.

Еще вариант - через менеджер записи, заполняя оба измерения.
27. SanchoD 316 25.12.23 17:16 Сейчас в теме
В итоге сделал так:

МассивМарок = Докум.АкцизныеМарки.ВыгрузитьКолонку("АкцизнаяМарка");
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	АкцизныеМаркиЕГАИС.ОрганизацияЕГАИС КАК ОрганизацияЕГАИС,
	|	АкцизныеМаркиЕГАИС.АкцизнаяМарка КАК АкцизнаяМарка
	|ИЗ
	|	РегистрСведений.АкцизныеМаркиЕГАИС КАК АкцизныеМаркиЕГАИС
	|ГДЕ
	|	АкцизныеМаркиЕГАИС.АкцизнаяМарка В(&АкцизнаяМарка)";
	
	Запрос.УстановитьПараметр("АкцизнаяМарка", МассивМарок);
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Выборка = РезультатЗапроса.Выбрать();
	Пока Выборка.Следующий() Цикл
		МЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьМенеджерЗаписи();
		МЗ.ОрганизацияЕГАИС = Выборка.ОрганизацияЕГАИС;
		МЗ.АкцизнаяМарка = Выборка.АкцизнаяМарка;
		Попытка
			МЗ.Удалить();	
		Исключение
			Сообщить(ОписаниеОшибки());	
		КонецПопытки;	
	КонецЦикла;
Показать


удаление одной записи (включая поиск0 заняло 0,2 секунды. Т.е. в 175 раз быстрее лучшего предыдущего варианта, предложенного в (4).
Т.е. удаление через запись набора с отбором не лучший вариант.

Всем спасибо за помощь!
28. spacecraft 25.12.23 17:32 Сейчас в теме
(27)
Т.е. в 175 раз быстрее лучшего предыдущего варианта, предложенного в (4).

Ну, не поняли так не поняли...
29. SanchoD 316 25.12.23 18:00 Сейчас в теме
(28) Я в данном случае не разделяю на получение данных и удаление. Имеет значение сколько всего времени ушло на выполнение обработки в расчете на обрабатываемую марку. И данные такие, в старом алгоритме 45 секунд на марку затрачивалось, в Вашем 35 секунд, в конечном варианте 0,2 секунды.
Или речь о другом?
30. spacecraft 25.12.23 18:15 Сейчас в теме
(29)
Или речь о другом?

О другом. В 4 был дан вариант делать все в одной транзакции. Так быстрее запишется.
Далее было объяснено, почему долго обрабатывалось (из-за поиска не в индексе).
Далее были даны рекомендации получения данных, чтобы использовать индексы.
В итоге используете менеджер записи вместо набора. Только сам менеджер внутри использует тот же самый набор записей. Но так как теперь Отбор устанавливается с учетом поиска по кластерному индексу, то и отрабатывает быстрее, как и было сказано, на несколько порядков быстрее.

Теперь попробуйте все соединить вместе. Можно отдельный массив не делать, но и не помешает. Чтобы уменьшить время транзакции.
31. SanchoD 316 25.12.23 19:50 Сейчас в теме
(30) В отладчике так распределялось время выполнения.
При записи набора с установленным отбором по АкцизнойМарке, на НЗ.Записать() приходилось 98% времени.
На 120 элементов (АМ) ушло в итоге 1,5 часа.
При получении выборки запросом, на выполнение запроса пришлось 65% времени и 5% пришлось на выполнение метода МЗ.Удалить(). На 70 элементов (АМ) ушло в итоге 15 секунд.
32. spacecraft 25.12.23 20:14 Сейчас в теме
(31) вот даже не знаю что еще добавить к (30). Там все есть подробно.
Вот еще подсказка.
Вместо:
МЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьМенеджерЗаписи();
МЗ.ОрганизацияЕГАИС = Выборка.ОрганизацияЕГАИС;
МЗ.АкцизнаяМарка = Выборка.АкцизнаяМарка;
Попытка
МЗ.Удалить();

Можно записать так:
МЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьНаборЗаписей();
МЗ.Отбор.ОрганизацияЕГАИС.Установить(Выборка.ОрганизацияЕГАИС);
МЗ.Отбор.АкцизнаяМарка.Установить(Выборка.АкцизнаяМарка);
МЗ.Записать();

Что в итоге одно и тоже. МенеджерЗаписи внутри использует этот же набор записей. Так что не корректно говорить, что менеджер записи будет быстрее.
33. SanchoD 316 25.12.23 20:21 Сейчас в теме
(32) Идею понял. Попробую протестить.
Я имел ввиду не то, что менеджер записи быстрее набора записей, а то что метод Удалить() работает быстрее чем Записать().
35. spacecraft 26.12.23 07:58 Сейчас в теме
(33)
Я имел ввиду не то, что менеджер записи быстрее набора записей, а то что метод Удалить() работает быстрее чем Записать().

Удалить() работает не так как представляете. Он не удаляет записи из регистра напрямую. Он удаляет запись из второго набора записей, который используется для записи новых значений. Да, менеджер записи использует 2!!! набора записей.
Ознакомьтесь, что вообще собой представляет менеджер записи и как он работает.
https://its.1c.ru/db/metod8dev/content/2722/hdoc
36. Sashares 35 26.12.23 11:36 Сейчас в теме
(33)И как, быстрее через набор записей удалять?
Ставлю, что разница от менеджера записи будет на уровне погрешности.
37. SanchoD 316 27.12.23 12:33 Сейчас в теме
(32) Протестил оба варианта. Докладываю.

МЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьМенеджерЗаписи();
		МЗ.ОрганизацияЕГАИС = Выборка.ОрганизацияЕГАИС;
		МЗ.АкцизнаяМарка = Выборка.АкцизнаяМарка;
		Попытка
			МЗ.Удалить();	
		Исключение
			Сообщить(ОписаниеОшибки());	
		КонецПопытки;	
Показать


Исполняется 0,0064 сек. на 1 элемент выборки.

НЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьНаборЗаписей();
		НЗ.Отбор.ОрганизацияЕГАИС.Установить(Выборка.ОрганизацияЕГАИС);
		НЗ.Отбор.АкцизнаяМарка.Установить(Выборка.АкцизнаяМарка);
		Попытка
			НЗ.Записать();	
		Исключение
			Сообщить(ОписаниеОшибки());	
		КонецПопытки;	


Исполняется 0,0066 сек. на 1 элемент выборки.
34. Said-We 26.12.23 00:51 Сейчас в теме
(1) Самое быстрое прямой запрос к SQL, но его нИЗЯ использовать. Но если разовая операция, то аккуратно можно.

Главное посмотреть есть или нет зависимых записей в других РС.
Например, в ЗиУП есть РС, в которых хранятся периоды изменения значений с постфиксом "интервальный". Т.е. если что-то удалять в РС исходнике, то записи интервального регистра необходимо переформировывать.

Сами удаляемые марки, у Вас же хранятся в документе. Значит остается найти этот нужный список марок и просто удалить записи из РС.
DELETE FR OM <имя таблицы> 
WH ERE АкцизнаяМарка IN (SEL ECT АкцизнаяМарка FR OM ...)
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот