Как ускорить длительное заполнение документа «Формирование записей книги продаж» в 1С:УПП 1.3?

Программист 1С v8.3 (Обычные формы) Налоговый учет IT и автоматизация бизнеса
← На главную

При ведении учета в конфигурации «1С:Управление производственным предприятием 1.3» на предприятиях с большим документооборотом (десятки тысяч реализаций и счетов-фактур в квартал) пользователи часто сталкиваются с существенным замедлением регламентных операций по НДС. Документ Формирование записей книги продаж при нажатии кнопки заполнения может выполняться десятки минут или приводить к зависанию сеанса.

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

Причина падения производительности в типовом алгоритме

Проанализируем работу типовой подсистемы учета НДС. Независимо от выбранной учетной политики по моменту начисления НДС («по отгрузке» или «по оплате»), типовой механизм сопоставляет выставленные счета-фактуры и прошедшие платежи. Это необходимо, чтобы корректно выделить авансовые и частичные оплаты, а также заполнить реквизиты платежно-расчетных документов в строках книги продаж.

Основное «бутылочное горлышко» находится в модуле объекта документа ФормированиеЗаписейКнигиПродаж, а именно в процедуре РаспределитьОплатыПоДеревуСФ. В типовой реализации применен неоптимальный шаблон:

  1. Формируется общее дерево начисленного НДС и таблица распределенных оплат размером в десятки тысяч записей.
  2. Запускается цикл по всем строкам дерева счетов-фактур.
  3. На каждой итерации цикла настраивается и выполняется объект ПостроительЗапроса, обращающийся к неиндексированной таблице значений.

Выполнение десятков тысяч последовательных запросов через ПостроительЗапроса к коллекции в оперативной памяти создает колоссальную нагрузку на процессор и приводит к геометрическому росту времени обработки.

Решение 1. Оптимизация алгоритма распределения оплат в модуле объекта

Для кардинального ускорения заполнения перепишем процедуру РаспределитьОплатыПоДеревуСФ. Откажемся от использования ПостроительЗапроса внутри цикла, добавим индекс по ключевому полю СчетФактура и применим быстрый платформенный метод НайтиСтроки().

Рассмотрим по шагам модификацию процедуры в модуле объекта документа ФормированиеЗаписейКнигиПродаж:


Процедура РаспределитьОплатыПоДеревуСФ(Дерево_НДСНачисленный, ТаблицаРезультатов, СписокСчетовФактур, РаспределенныеОплаты, ОтражатьВРеестре = Истина, ОтражатьВидНачисления = Ложь)
    
    НДСНалоговыйПериод = Неопределено;
    
    ТаблицаОплат = Новый ТаблицаЗначений();
    ТаблицаОплат.Колонки.Добавить("ДокументОплаты");
    ТаблицаОплат.Колонки.Добавить("ДатаОплаты", Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)));
    ТаблицаОплат.Колонки.Добавить("СуммаОплаты", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
    
    // Создаем копию таблицы распределенных оплат и индексируем ее для быстрого поиска
    ТаблицаИсточникаПостроителя = РаспределенныеОплаты.Скопировать();
    ТаблицаИсточникаПостроителя.Индексы.Добавить("СчетФактура");
    ВыборкаОплат = РаспределенныеОплаты.СкопироватьКолонки();
    
    МоментОпределения_ПоОтгрузке = Перечисления.МоментыОпределенияНалоговойБазыНДС.ПоОтгрузке;
    
    Для Каждого СтрокаСФ Из Дерево_НДСНачисленный.Строки Цикл
        
        ТаблицаОплат.Очистить();
        
        Если УчетНДС.ДляСчетаФактурыНеТребуетсяОплата(СтрокаСФ.СчетФактура) Тогда
            НаличиеОплатыНеТребуется = Истина;
        Иначе
            НаличиеОплатыНеТребуется = (СтрокаСФ.Строки[0].МоментОпределенияНалоговойБазыНДС = МоментОпределения_ПоОтгрузке) Или Дата >= '20080101';
            
            // Быстрый поиск строк по индексу вместо ПостроителяЗапроса
            МассивСтрокОплатПоСФ = ТаблицаИсточникаПостроителя.НайтиСтроки(Новый Структура("СчетФактура", СтрокаСФ.СчетФактура));
            
            // Обработка ситуации, когда оплата отсутствует
            Если МассивСтрокОплатПоСФ.Количество() = 0 И Не НаличиеОплатыНеТребуется И СтрокаСФ.СуммаСНДС >= 0 Тогда
                Продолжить;
            КонецЕсли;
            
            ВыборкаОплат.Очистить();
            Для Каждого СтрокаОплатыПоСФ Из МассивСтрокОплатПоСФ Цикл
                Если ((СтрокаСФ.СуммаСНДС > 0) И (СтрокаОплатыПоСФ.РаспределеннаяОплата > 0)) Или 
                     ((СтрокаСФ.СуммаСНДС <= 0) И (СтрокаОплатыПоСФ.РаспределеннаяОплата < 0)) Тогда
                    
                    СтрокаВыборкиОплат = ВыборкаОплат.Добавить();
                    Для Каждого Колонка Из ВыборкаОплат.Колонки Цикл
                        ИндексКолонки = ВыборкаОплат.Колонки.Индекс(Колонка);
                        СтрокаВыборкиОплат.Установить(ИндексКолонки, СтрокаОплатыПоСФ.Получить(ИндексКолонки));
                    КонецЦикла;
                КонецЕсли;
            КонецЦикла;
            
            ВыборкаОплат.Сортировать("ДатаОплаты");
            
            СуммаКПогашению = СтрокаСФ.СуммаСНДС;
            Для Каждого СтрокаРаспределеннойОплаты Из ВыборкаОплат Цикл
                // Далее идет типовой неизмененный код распределения сумм

Благодаря исключению накладных расходов на инициализацию парсера запросов и использованию индекса по полю СчетФактура, время сопоставления сотен и тысяч документов сокращается в десятки раз (с 30–40 минут до считанных секунд).

Решение 2. Комплексная оптимизация подсистемы учета НДС

Если после доработки программного кода время формирования документа остается значительным, проанализируем сопутствующие факторы производительности:

  1. Проверка и закрытие «хвостов» в регистрах НДС: Накопление незакрытых остатков за прошлые налоговые периоды в регистрах НДС расчеты с покупателями, НДС начисленный и НДС с авансов раздувает размер входных таблиц. Рекомендуется закрывать зависшие копеечные остатки с помощью документа Корректировка записей регистров.
  2. Дробление регламентных документов: На предприятиях с филиальной структурой или масштабным оборотом целесообразно создавать несколько документов Формирование записей книги продаж (разбивая их помесячно или по организациям), что снижает объем единовременно удерживаемых коллекций в оперативной памяти.
  3. Обслуживание базы данных на стороне СУБД: Перед формированием регламентной отчетности по НДС обязательно выполните регламентные процедуры СУБД — обновление статистик (UPDATE STATISTICS с полным сканированием) и дефрагментацию/реиндексацию таблиц итогов регистров накопления.
  4. Использование 64-разрядного сервера 1С: При интенсивной обработке массивов данных 32-разрядный рабочий процесс rphost может исчерпать доступное адресное пространство памяти (2–3 ГБ) и аварийно завершиться. Переход на 64-битный сервер полностью решает проблему нехватки памяти при формировании объемных книг покупок и продаж.
← На главную