Как обойти ограничение размера табличной части и обработать более 100 000 строк в документе 1С?

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

При проектировании систем в 1С разработчики нередко сталкиваются с необходимостью загрузки и обработки массивов данных объемом в сотни тысяч строк (чеки, биллинг, детальные выгрузки из внешних систем). Стандартная табличная часть документа исторически имеет жесткое платформенное ограничение на 99 999 строк, связанное с фиксированной длиной служебного поля НомерСтроки (LineNo). Попытки обойти это ограничение «в лоб» часто приводят к падению производительности и ошибкам переполнения памяти.

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

Почему нельзя использовать Таблицу Значений на форме

Частая идея начинающих разработчиков — создать реквизит формы с типом ТаблицаЗначений и загружать данные в него, считывая или записывая их в регистр сведений. Проанализируем, к чему это приводит на практике:

  1. Контекстная сериализация: На управляемых формах при каждом серверном вызове данные формы целиком передаются между клиентом и сервером. Коллекция из 100 000+ строк при вызовах процедур ЗначениеВДанныеФормы и ДанныеФормыВЗначение вызывает колоссальный трафик и зависание интерфейса.
  2. Переполнение памяти на клиенте: В отличие от динамических списков, таблица значений загружается в оперативную память клиента целиком, что вызывает ошибку Memory Allocation Error и аварийное завершение сеанса.
  3. Эскалация блокировок в СУБД: Запись объекта с сотнями тысяч строк внутри одной транзакции блокирует таблицы СУБД целиком, парализуя работу остальных пользователей.

Вариант 1. Отображение через Динамический список и Регистр Сведений

Рассмотрим правильную реализацию хранения строк вне табличной части. Данные строк сохраняются в регистр сведений, а на форму документа помещается ДинамическийСписок.

При реализации этого подхода важно учитывать следующие правила:

  1. Связь с документом: Создаем в регистре сведений измерение (например, ДокументОснование) с типом ссылки на наш документ. Устанавливаем свойство Ведущее — это обеспечит автоматический контроль ссылочной целостности и удаление записей при удалении документа.
  2. Настройка динамического списка: В свойствах списка обязательно указываем свойство ОсновнаяТаблица (наш регистр сведений). Не используем произвольные запросы с соединениями к неиндексированным таблицам. Это позволяет платформе выполнять быструю серверную пагинацию (порционную выборку данных по мере прокрутки списка пользователем).
  3. Редактирование данных: Редактирование записей можно выполнять непосредственно в строках динамического списка без открытия отдельной формы записи, если настроить свойства колонок и элементов управления.

Вариант 2. Архитектура «Один документ — одна строка» (Подчиненные документы)

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

  1. Создается легкий документ, содержащий только реквизиты шапки (номенклатура, количество, сумма, ссылка на родительский пакет).
  2. В основном документе-контейнере на форму выводится динамический список подчиненных документов с отбором по ссылке на родительский документ.
  3. Проведение и расчет движений распределяются по отдельным транзакциям, что исключает долгие взаимоблокировки в СУБД.

Вариант 3. Хранилище значения и потоковая обработка (Staging data)

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

  1. Исходный массив сохраняется в реквизит документа с типом ХранилищеЗначения в виде сжатого файла, JSON или бинарного потока.
  2. На форме отображаются только итоговые показатели (общее количество, контрольная сумма, статус обработки).
  3. В процедуре проведения или фоновом задании чтение выполняется потоковыми объектами (например, ЧтениеJSON или ЧтениеXML) без загрузки всего массива в оперативную память.

Посмотрим на пример порционной записи наборов движений при потоковой обработке:


// Порционная запись движений для предотвращения переполнения памяти
Набор = РегистрыНакопления.Продажи.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(Ссылка);

Счетчик = 0;
Для Каждого СтрокаДанных Из ПотокДанных Цикл
    Движение = Набор.Добавить();
    ЗаполнитьЗначенияСвойств(Движение, СтрокаДанных);
    
    Счетчик = Счетчик + 1;
    Если Счетчик % 5000 = 0 Тогда
        // Записываем порцию и очищаем набор
        Набор.Записать(Ложь);
        Набор.Очистить();
    КонецЕсли;
КонецЦикла;

Если Набор.Количество() > 0 Тогда
    Набор.Записать(Ложь);
КонецЕсли;

Рекомендации по оптимизации сверхбольших массивов

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

  1. Длина номера строки в новых версиях платформы: Начиная с версии 1С:Предприятия 8.3.27, для табличных частей доступно свойство «Длина номера строки» (значения от 5 до 9), позволяющее расширить физический лимит строк в ТЧ до 999 999 999. Однако использовать стандартную ТЧ на управляемой форме при таком количестве строк все равно не рекомендуется из-за накладных расходов на сериализацию контекста формы.
  2. Отключение версионирования: Для документов и регистров с большими объемами данных обязательно отключаем версионирование объектов в подсистеме БСП, иначе база данных будет экспоненциально расти при каждой перезаписи объекта.
  3. Постраничный интерфейс (Пагинация): Если пользователю необходим просмотр большого массива, проектируем форму с параметризованным буфером на 100–500 строк и кнопками навигации («Вперед / Назад»), подгружая данные порциями через запрос с отбором по индексу.
← На главную