Столкнулся с такой проблемой. Есть регистр сведений, где свыше 50 млн. записей. В нем 2 измерения. Нужно удалить записи, где одно из измерений находится в массиве порядка 1000 элементов.
Делаю перебор массива, устанавливаю отбор для набора записей равный выбранному элементу и записываю набор.
Таким образом реализую что и требуется. Но достаточно медленно.
Можно ли каким-то альтернативным путем удалить записи регистра?
(4) Такой вариант дал прирост быстродействия в 22%. По старому алгоритму уходило 45 секунд на одну марку, по новому 35 секунд. Это лучше чем было, но не существенно ускоряет процесс. 1000 элементов будет обрабатываться не 12,5 часов, а 10.
(16) замеры как производились? Если в отладчике, то это не замеры производительности алгоритма, а замеры работы отладчика.
Ну и чуда тоже ожидать не следует.
МассивМарок = Докум.АкцизныеМарки.ВыгрузитьКолонку("АкцизнаяМарка");
Для xxx=0 По МассивМарок.ВГраница() Цикл
НЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьНаборЗаписей();
НЗ.Отбор.АкцизнаяМарка.Установить(МассивМарок[xxx]);
Если ЗаписатьОбъект(НЗ) Тогда
Сообщить("Очищена запись в РС по марке: " + МассивМарок[xxx]);
КонецЕсли;
КонецЦикла;
(3) ТабЗначений это полученные записи регистра с отбором Измерение1 В(МассивЭлементов)? Тогда остануться только они, а удалятся все остальные. Или ТабЗначений это 50 млн. записей без нескольких тысяч?
Ну это верная смерть для процесса.
(6) если использовать код в (3), то сначала платформа будет "обнулять" таблицу из около 50КК записей, а потом записывать записи в количестве ТабЗначений.Количество()
Не упадет, на современных платформах все ок с такими объемами?
(17) что именно "Почему"?
Долго или быстро?
Предположу, что измерение не первое и не указано "Индексировать".
Основное время тратится на поиск записей.
устанавливается отбор по значению неиндексируемого измерения. Чтобы найти нужные записи в 50млн записях потребуется очень много времени. Вот основное время и тратится на этот поиск.
(20) а вот нужно удалить именно только по АкцизнаяМарка?
Если устанавливать еще и первое измерение в отбор, то будет использоваться кластерный индекс и время поиска сократится на порядки.
МассивМарок = Докум.АкцизныеМарки.ВыгрузитьКолонку("АкцизнаяМарка");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| АкцизныеМаркиЕГАИС.ОрганизацияЕГАИС КАК ОрганизацияЕГАИС,
| АкцизныеМаркиЕГАИС.АкцизнаяМарка КАК АкцизнаяМарка
|ИЗ
| РегистрСведений.АкцизныеМаркиЕГАИС КАК АкцизныеМаркиЕГАИС
|ГДЕ
| АкцизныеМаркиЕГАИС.АкцизнаяМарка В(&АкцизнаяМарка)";
Запрос.УстановитьПараметр("АкцизнаяМарка", МассивМарок);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
МЗ = РегистрыСведений.АкцизныеМаркиЕГАИС.СоздатьМенеджерЗаписи();
МЗ.ОрганизацияЕГАИС = Выборка.ОрганизацияЕГАИС;
МЗ.АкцизнаяМарка = Выборка.АкцизнаяМарка;
Попытка
МЗ.Удалить();
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Показать
удаление одной записи (включая поиск0 заняло 0,2 секунды. Т.е. в 175 раз быстрее лучшего предыдущего варианта, предложенного в (4).
Т.е. удаление через запись набора с отбором не лучший вариант.
(28) Я в данном случае не разделяю на получение данных и удаление. Имеет значение сколько всего времени ушло на выполнение обработки в расчете на обрабатываемую марку. И данные такие, в старом алгоритме 45 секунд на марку затрачивалось, в Вашем 35 секунд, в конечном варианте 0,2 секунды.
Или речь о другом?
О другом. В 4 был дан вариант делать все в одной транзакции. Так быстрее запишется.
Далее было объяснено, почему долго обрабатывалось (из-за поиска не в индексе).
Далее были даны рекомендации получения данных, чтобы использовать индексы.
В итоге используете менеджер записи вместо набора. Только сам менеджер внутри использует тот же самый набор записей. Но так как теперь Отбор устанавливается с учетом поиска по кластерному индексу, то и отрабатывает быстрее, как и было сказано, на несколько порядков быстрее.
Теперь попробуйте все соединить вместе. Можно отдельный массив не делать, но и не помешает. Чтобы уменьшить время транзакции.
(30) В отладчике так распределялось время выполнения.
При записи набора с установленным отбором по АкцизнойМарке, на НЗ.Записать() приходилось 98% времени.
На 120 элементов (АМ) ушло в итоге 1,5 часа.
При получении выборки запросом, на выполнение запроса пришлось 65% времени и 5% пришлось на выполнение метода МЗ.Удалить(). На 70 элементов (АМ) ушло в итоге 15 секунд.
(32) Идею понял. Попробую протестить.
Я имел ввиду не то, что менеджер записи быстрее набора записей, а то что метод Удалить() работает быстрее чем Записать().
Я имел ввиду не то, что менеджер записи быстрее набора записей, а то что метод Удалить() работает быстрее чем Записать().
Удалить() работает не так как представляете. Он не удаляет записи из регистра напрямую. Он удаляет запись из второго набора записей, который используется для записи новых значений. Да, менеджер записи использует 2!!! набора записей.
Ознакомьтесь, что вообще собой представляет менеджер записи и как он работает.
https://its.1c.ru/db/metod8dev/content/2722/hdoc
(1) Самое быстрое прямой запрос к SQL, но его нИЗЯ использовать. Но если разовая операция, то аккуратно можно.
Главное посмотреть есть или нет зависимых записей в других РС.
Например, в ЗиУП есть РС, в которых хранятся периоды изменения значений с постфиксом "интервальный". Т.е. если что-то удалять в РС исходнике, то записи интервального регистра необходимо переформировывать.
Сами удаляемые марки, у Вас же хранятся в документе. Значит остается найти этот нужный список марок и просто удалить записи из РС.
DELETE FR OM <имя таблицы>
WH ERE АкцизнаяМарка IN (SEL ECT АкцизнаяМарка FR OM ...)