Как организовать хранение больших объемов детальной информации к строкам документа в 1С?

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

В процессе разработки сложных учетных систем на платформе 1С:Предприятие 8.3 мы часто сталкиваемся с дилеммой: где хранить подробную расшифровку расчетов. Представим ситуацию: у нас есть документ начисления, содержащий 5 000 сотрудников. Для каждого сотрудника необходимо хранить детализацию по дням (30-31 строка) с десятком различных параметров. Попытка записать всё это в обычную табличную часть приведет к созданию 150 000 строк в одном документе. Это неизбежно вызовет проблемы с производительностью при открытии формы, проведении и передаче данных между клиентом и сервером.

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

Вариант 1. Использование непериодического регистра сведений

Это классический и наиболее рекомендуемый подход для хранения первичных данных, которые не должны перегружать сам объект (документ). Мы создаем РегистрСведений, который будет выступать внешним хранилищем для нашей детализации.

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

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

Посмотрим на пример генерации связи при добавлении строки в документ:


// Консоль кода + ИИ-помощник поможет быстро сгенерировать подобные обработчики
&НаКлиенте
Процедура ОсновнаяТЧПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
    Если НоваяСтрока Тогда
        ТекущиеДанные = Элементы.ОсновнаяТЧ.ТекущиеДанные;
        ТекущиеДанные.ИдентификаторСтроки = Строка(Новый УникальныйИдентификатор);
    КонецЕсли;
КонецПроцедуры

Преимущества: данные не грузятся при открытии документа, их легко анализировать запросами или через СКД. Недостатки: риск рассинхронизации данных при удалении документа или строк (необходимо прописывать логику очистки регистра в модуле объекта).

Вариант 2. Вторая (подчиненная) табличная часть

Если объем данных не критичен для СУБД (например, до 50 000 строк в сумме), можно использовать вторую табличную часть в том же документе. Связь осуществляется так же через ИдентификаторСтроки или номер строки основной ТЧ.

Проанализируем ситуацию: если мы выберем этот вариант, платформа будет считывать ВСЕ 150 000 строк при каждом обращении к объекту на сервере. Это значительно замедлит работу функции ПолучитьОбъект(). Однако, если пользователю нужно видеть детализацию редко, мы можем использовать оптимизированную передачу данных и не выводить вторую ТЧ на форму сразу, а подгружать данные только для текущей строки основной таблицы.

Вариант 3. Хранилище значения в строке табличной части

Рассмотрим нестандартный подход, который выбрал автор темы. Он заключается в хранении всей детализации по одной строке в одном поле типа ХранилищеЗначения. В это поле упаковывается Соответствие или Структура, содержащая массив данных по дням.

Разберем пример кода для записи таких данных:


// В модуле объекта или обработке расчета
Для Каждого СтрокаТЧ Из ОсновнаяТЧ Цикл
    СтруктураДеталей = Новый Структура;
    // Заполняем структуру расчетами по дням
    СтруктураДеталей.Вставить("ДанныеДня", СписокПараметров);
    
    // Помещаем в ХранилищеЗначения
    СтрокаТЧ.Детализация = Новый ХранилищеЗначения(СтруктураДеталей, Новый СжатиеДанных(9));
КонецЦикла;

Почему это работает: реквизиты типа ХранилищеЗначения не передаются автоматически с сервера на клиент в составе контекста формы. Это позволяет основной ТЧ оставаться "легкой" для интерфейса. Однако у этого метода есть огромный минус: данные внутри ХранилищаЗначения невозможно извлечь обычным запросом. Для построения любого отчета по дням вам придется перебирать все документы программно.

Вариант 4. Регистры расчета и графики

Если ваша задача — это начисления (зарплата, аренда, услуги), то наиболее правильным инструментом является РегистрРасчета. Рассмотрим подробнее его возможности:

Вариант 5. Использование JSON для технической детализации

Если данные нужны только для аудита ("как получилась эта цифра?"), проанализируем вариант с форматом JSON. Мы можем упаковать детализацию строки в компактную JSON-строку и хранить ее в длинном строковом реквизите (неограниченной длины).

Посмотрим на пример сериализации:


ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивНашихДетальныхДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();

// Записываем в реквизит строки ТЧ
СтрокаТЧ.ТехническийДамп = СтрокаJSON;

Это современный и кроссплатформенный способ. JSON занимает меньше места, чем сериализованная структура 1С, и при необходимости может быть проанализирован внешними инструментами напрямую из базы данных SQL.

Итоги и рекомендации

Выяснив причины и проанализировав все способы, дадим финальный совет:

  1. Если данные нужны для отчетов — используйте только РегистрСведений. Это обеспечит максимальную производительность запросов.
  2. Если данных очень много (миллионы) — рассмотрите вынос детализации в отдельные "технические" документы, чтобы основной документ начисления открывался мгновенно.
  3. Если важна простота разработки и данные носят справочный характер — используйте ХранилищеЗначения или JSON-строку, но помните о невозможности построения запросов по этим данным.
  4. Всегда очищайте данные. Если вы выбрали внешнее хранилище (регистр), не забудьте добавить код в подписку на событие ПередУдалением документа, чтобы не забивать базу "сиротскими" записями.

Выбор архитектуры зависит от баланса между скоростью записи, удобством чтения и сложностью поддержки кода. Для большинства высоконагруженных систем 1С связка "Документ + Регистр Сведений" остается золотым стандартом.

← На главную