Стимулом к внесению исправлений в обработку является желание исправить ошибки и сократить время работы.
Платформа 1С:Предприятие 8.3 (8.3.12.1440)
Обработка кпкОчисткаТрековЗаПериод входит в поставку программного комплекса АгентПлюс мобильная торговля и предназначена для удаления записей регистра сведений за период по выбранным торговым агентам (Далее ТА).
Стимулом к внесению исправлений в обработку является желание исправить ошибки и сократить время работы.
Ошибка.
В обработке есть цикл формирования списка по выбранным ТА. Но в цикле нет проверки на то, что является выбранным , а что нет.
Было:
Для Каждого СтрокаМас Из МассивАгентов Цикл
СписАгентов.Добавить(СтрокаМас);
КонецЦикла;
Стало:
Для Каждого СтрокаТаб Из ТаблицаАгентов Цикл
Если СтрокаТаб.Пометка Тогда
СписАгентов.Добавить(СтрокаТаб.Агент);
КонецЕсли;
КонецЦикла;
Кроме того в Процедуре ЗаполнитьТаблицуАгентов Испльзуется запрос к РС кпкСведенияАгента, что не дает возможности получить весь список ТА когда либо работавших на предприятии. Поэтому вносились изменения и в процедуру ЗаполнитьТаблицуАгентов.
Было:
ВыборкаРегистра = РегистрыСведений.кпкСведенияАгента.Выбрать();
Пока ВыборкаРегистра.Следующий() Цикл
СтрАгента = ТаблицаАгентов.Добавить();
СтрАгента.Агент = ВыборкаРегистра.Объект;
СтрАгента.Пометка = Истина;
КонецЦикла;
Стало:
Процедура ЗаполнитьТаблицуАгентов() Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| кпкСведенияПоГПСТрекам.Агент КАК Агент,
| кпкСведенияПоГПСТрекам.Агент.Наименование КАК Наименование
|
|ИЗ
| РегистрСведений.кпкСведенияПоГПСТрекам КАК кпкСведенияПоГПСТрекам
|
|СГРУППИРОВАТЬ ПО
| кпкСведенияПоГПСТрекам.Агент
|
|УПОРЯДОЧИТЬ ПО
| Наименование
|
|";
ВыборкаРегистра = Запрос.Выполнить().Выбрать();
ТаблицаАгентов.Очистить();
Пока ВыборкаРегистра.Следующий() Цикл
СтрАгента = ТаблицаАгентов.Добавить();
СтрАгента.Агент = ВыборкаРегистра.Агент;
СтрАгента.Пометка = Истина;
КонецЦикла;
КонецПроцедуры
Изменения коснулись и главной процедуры ВыполнитьОчисткуТреков. Дело в том, что авторами предложен метод удаления записей регистров по одной используя Менеджер. Этот метод чрезвычайно медленный и в случае удаления за длительный период обработка выполняется чрезвычайно долго.
Было:
Процедура ВыполнитьОчисткуТреков() Экспорт
МассивАгентов = ТаблицаАгентов.ВыгрузитьКолонку("Агент");
СписАгентов = Новый СписокЗначений;
Для Каждого СтрокаМас Из МассивАгентов Цикл
СписАгентов.Добавить(СтрокаМас);
КонецЦикла;
Запрос = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ
| кпкСведенияПоГПСТрекам.Период,
| кпкСведенияПоГПСТрекам.Агент,
| кпкСведенияПоГПСТрекам.ДатаСоздания,
| кпкСведенияПоГПСТрекам.Широта,
| кпкСведенияПоГПСТрекам.Долгота,
| кпкСведенияПоГПСТрекам.Ключ
|ИЗ
| РегистрСведений.кпкСведенияПоГПСТрекам КАК кпкСведенияПоГПСТрекам
|ГДЕ
| кпкСведенияПоГПСТрекам.Период МЕЖДУ &НачПериод И &КонПериод
| И кпкСведенияПоГПСТрекам.Агент В(&СписокАгентов)");
Запрос.УстановитьПараметр("НачПериод", НачалоДня(НачПериода));
Запрос.УстановитьПараметр("КонПериод", КонецДня(КонПериода));
Запрос.УстановитьПараметр("СписокАгентов", СписАгентов);
ВыборкаГПС = Запрос.Выполнить().Выбрать();
Менеджер = РегистрыСведений.кпкСведенияПоГПСТрекам.СоздатьМенеджерЗаписи();
Пока ВыборкаГПС.Следующий() Цикл
Менеджер.Период = ВыборкаГПС.Период;
Менеджер.Агент = ВыборкаГПС.Агент;
Менеджер.Ключ = ВыборкаГПС.Ключ;
Менеджер.Прочитать();
Если Менеджер.Выбран() Тогда
Менеджер.Удалить();
КонецЕсли;
КонецЦикла;
КонецПроцедуры //ВыполнитьОчисткуТреков()
Стало:
Процедура ВыполнитьОчисткуТреков() Экспорт
СписАгентов = Новый СписокЗначений;
Для Каждого СтрокаТаб Из ТаблицаАгентов Цикл
Если СтрокаТаб.Пометка Тогда
СписАгентов.Добавить(СтрокаТаб.Агент);
КонецЕсли;
КонецЦикла;
Сообщить("Начало Выполнения "+ТекущаяДата());
Запрос = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ *
|
|ИЗ
| РегистрСведений.кпкСведенияПоГПСТрекам КАК кпкСведенияПоГПСТрекам
|ГДЕ
|
| НЕ
| (кпкСведенияПоГПСТрекам.Период МЕЖДУ &НачПериод И &КонПериод
| И кпкСведенияПоГПСТрекам.Агент В(&СписокАгентов))
|
|");
Запрос.УстановитьПараметр("НачПериод", НачалоДня(НачПериода));
Запрос.УстановитьПараметр("КонПериод", КонецДня(КонПериода));
Запрос.УстановитьПараметр("СписокАгентов", СписАгентов);
ТЗ = Запрос.Выполнить().Выгрузить();
Сообщить("Запрос Выполнен "+ТекущаяДата());
Запрос2 = Новый Запрос("ВЫБРАТЬ РАЗРЕШЕННЫЕ
| кпкСведенияПоГПСТрекам.Период,
| кпкСведенияПоГПСТрекам.Агент,
| кпкСведенияПоГПСТрекам.ДатаСоздания,
| кпкСведенияПоГПСТрекам.Широта,
| кпкСведенияПоГПСТрекам.Долгота,
| кпкСведенияПоГПСТрекам.Ключ
|ИЗ
| РегистрСведений.кпкСведенияПоГПСТрекам КАК кпкСведенияПоГПСТрекам
|ГДЕ
| кпкСведенияПоГПСТрекам.Период МЕЖДУ &НачПериод И &КонПериод
| И кпкСведенияПоГПСТрекам.Агент В(&СписокАгентов)");
Запрос2.УстановитьПараметр("НачПериод", НачалоДня(НачПериода));
Запрос2.УстановитьПараметр("КонПериод", КонецДня(КонПериода));
Запрос2.УстановитьПараметр("СписокАгентов", СписАгентов);
ВыборкаГПС = Запрос2.Выполнить().Выбрать();
Сообщить("Записий К Удалению: "+ВыборкаГПС.Количество());
Сообщить("Останется Записей: "+ТЗ.Количество());
Если (ТЗ.Количество() > 100000) Тогда
Сообщить("Записей к удалению "+ВыборкаГПС.Количество()+" "+ТекущаяДата());
//Запрос 2 т.е. Оригинал
Менеджер = РегистрыСведений.кпкСведенияПоГПСТрекам.СоздатьМенеджерЗаписи();
Сообщить("Работает Оригинальный способ "+ТекущаяДата());
Счетчик = 1;
Сч100 =1;
Пока ВыборкаГПС.Следующий() Цикл
Менеджер.Период = ВыборкаГПС.Период;
Менеджер.Агент = ВыборкаГПС.Агент;
Менеджер.Ключ = ВыборкаГПС.Ключ;
Менеджер.Прочитать();
Если Менеджер.Выбран() Тогда
Менеджер.Удалить();
КонецЕсли;
Если Сч100 = 1000 Тогда
Сообщить("Обработано: " +Счетчик+"-- "+ТекущаяДата());
Сч100= 0;
КонецЕсли;
Счетчик = Счетчик +1;
Сч100=Сч100+1;
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Обработано: " +(Счетчик-1)+"-- "+ТекущаяДата());
Иначе
//Запрос 1
Сообщить("Метод от остатка");
Сообщить("Остаток Записей "+ТЗ.Количество()+" "+ТекущаяДата());
НаборЗаписей = РегистрыСведений.кпкСведенияПоГПСТрекам.СоздатьНаборЗаписей();
НаборЗаписей.Загрузить(ТЗ);
Сообщить("Записи Загружены в РС "+ТекущаяДата());
ТЗ.Очистить();
Сообщить("ТЗ Очищена "+ТекущаяДата());
НаборЗаписей.Записать();
Сообщить("РС кпкСведенияПоГПСТрекам Записан! "+ТекущаяДата());
КонецЕсли;
КонецПроцедуры //ВыполнитьОчисткуТреков()
Некоторые пояснения.
- Предложен и реализован метод при котором переписываются только те записи РС, которые действительно необходимо оставить в РС.
- Опытным путем было получено ориентировочное число записей в 100000 при котором обработка не завершается ошибкой нехватки памяти.
- В случае если число записей РС , которые необходимо оставить в РС превышает 100000, обработка иcпользует оригинальный метод удаления, т.е. по записям с использованием Менеджера.
Выигрыш во времени колоссальный: удаление более 1го миллиона записей оригинальным методом длится более 5часов, удаление предложенным методом длится не более 2х минут.
Прошу знатоков высказать свое мнение по поводу предложенного метода работы с РС.