Как организовать компактное хранение и учет уникальных номеров товаров или бланков в 1С

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

При разработке систем учета часто возникает задача регистрации товаров с уникальными идентификаторами, например, бланков строгой отчетности, подарочных сертификатов или определенных серий продукции. Если записывать каждый номер отдельной строкой в РегистрНакопления, то при объемах в сотни тысяч или миллионы единиц база данных начинает стремительно расти, а производительность отчетов — падать. Рассмотрим, как решить проблему «раздувания» регистров, используя интервальное хранение и специализированные алгоритмы.

Проблема атомарного хранения и расщепления диапазонов

Представим ситуацию: на склад поступила пачка бланков с номерами от 1 до 1000. Классический подход 1С предполагает создание 1000 записей. Однако гораздо эффективнее хранить одну запись: [Товар 1, Серия А, Начало 1, Конец 1000, Кол-во 1000]. Проблема возникает в момент списания. Если клиент забирает бланк №50, наш красивый интервал 1–1000 должен превратиться в два новых: 1–49 и 51–1000. Проанализируем, как автоматизировать этот процесс и какие структуры данных для этого подходят.

Метод 1: Гибридная схема (Регистр накопления + Регистр сведений)

Это наиболее практичный способ для реализации в среде 1С. Суть заключается в разделении количественного учета и детальной информации о номерах. Разберем этот подход по шагам:

  1. Регистр накопления (Остатки): Здесь мы храним только общее количество товара в разрезе номенклатуры и серий, без указания конкретных номеров. Это позволяет системе быстро проводить документы и контролировать отрицательные остатки в типовом режиме.
  2. Регистр сведений (Интервалы): В этом регистре создаются измерения Номенклатура, Серия, НомерНачала и ресурс НомерКонца.
  3. Логика списания: При проведении документа расхода система обращается к регистру сведений, находит интервал, в который попадает требуемый номер (или набор номеров), и выполняет его пересчет.

Рассмотрим пример кода для расщепления интервала при списании одного номера. Допустим, у нас есть процедура, которая вызывается при проведении документа расхода:


Процедура ОбработатьСписаниеНомера(Товар, Серия, СписываемыйНомер)
    // Поиск интервала, в который входит номер
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Интервалы.НомерНачала КАК Нач,
        |   Интервалы.НомерКонца КАК Кон
        |ИЗ
        |   РегистрСведений.ИнтервалыНомеров КАК Интервалы
        |ГДЕ
        |   Интервалы.Номенклатура = &Товар
        |   И Интервалы.Серия = &Серия
        |   И &СписываемыйНомер МЕЖДУ Интервалы.НомерНачала И Интервалы.НомерКонца";
    
    Запрос.УстановитьПараметр("Товар", Товар);
    Запрос.УстановитьПараметр("Серия", Серия);
    Запрос.УстановитьПараметр("СписываемыйНомер", СписываемыйНомер);
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        Нач = Выборка.Нач;
        Кон = Выборка.Кон;
        
        // Удаляем старый интервал
        МенеджерЗаписи = РегистрыСведений.ИнтервалыНомеров.СоздатьМенеджерЗаписи();
        МенеджерЗаписи.Номенклатура = Товар;
        МенеджерЗаписи.Серия = Серия;
        МенеджерЗаписи.НомерНачала = Нач;
        МенеджерЗаписи.Прочитать();
        МенеджерЗаписи.Удалить();
        
        // Создаем новые интервалы (если есть остатки)
        Если СписываемыйНомер > Нач Тогда
            ЗаписатьНовыйИнтервал(Товар, Серия, Нач, СписываемыйНомер - 1);
        КонецЕсли;
        
        Если СписываемыйНомер < Кон Тогда
            ЗаписатьНовыйИнтервал(Товар, Серия, СписываемыйНомер + 1, Кон);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Метод 2: Дискретные деревья кодирования интервалов (DIET)

Проанализируем более продвинутый алгоритмический подход. DIET (Discrete Interval Encoding Trees) — это структура данных, специально созданная для хранения наборов целых чисел, образующих последовательности. В 1С это можно реализовать с помощью иерархического справочника, где каждый узел — это сбалансированный интервал.

Преимущества DIET:

Метод 3: Использование битовых масок и Roaring Bitmaps

Если ваши уникальные номера — это целые числа в определенном диапазоне, мы можем применить метод битовых карт. Рассмотрим ситуацию: для хранения информации о наличии 64 товаров нам достаточно одного числа типа Число (64-битное целое). Каждый бит в этом числе отвечает за конкретный номер: 1 — товар в наличии, 0 — продан.

Однако обычные битовые маски неэффективны, если номера распределены разреженно (например, есть номер 1 и номер 1 000 000). В этом случае стоит обратить внимание на технологию Roaring Bitmaps. Она разбивает пространство номеров на блоки. Если блок заполнен номерами подряд, он хранится как интервал. Если в блоке всего несколько номеров — как список. Если блок почти полон — как битовая маска. В 1С такую логику можно реализовать в виде зашифрованной строки в ХранилищеЗначения, обрабатывая её через COM-объект или внешнюю компоненту для максимальной скорости.

Метод 4: Подход «Острова и промежутки» (Gaps and Islands)

Иногда полезно не хранить интервалы в явном виде постоянно, а вычислять их в момент построения отчета. Мы можем хранить в РегистреНакопления только факты движения конкретных номеров. Чтобы превратить их в компактные интервалы в отчете, используется SQL-логика «Островов».

Разберем, как это работает на уровне логики запроса: мы нумеруем все имеющиеся номера товаров по порядку и вычитаем этот порядковый номер из самого значения идентификатора. Для всех номеров, идущих подряд, эта разность будет одинаковой. Группируя данные по этой разности, мы мгновенно получаем начало и конец каждого «острова» (непрерывного диапазона).

Проблема получения оборотов

При интервальном хранении получение классических оборотов за период (сколько раз списывался конкретный номер) становится сложнее. Выясним причину: в интервальном регистре мы видим только текущее состояние «свободных» номеров. Чтобы восстановить историю, необходимо:

  1. Либо вести лог всех операций в отдельном журнале (регистре сведений с регистрацией времени).
  2. Либо при формировании отчета «разворачивать» интервалы во временную таблицу. Для этого в запросе можно использовать соединение с вспомогательной таблицей чисел (итератором), которая превратит запись [1, 5] в пять строк 1, 2, 3, 4, 5.

Рекомендации по выбору решения

Проанализировав ситуацию, можно сделать следующие выводы:

  1. Если вам важна простота и типовые механизмы 1С — используйте Гибридную схему. Она дает баланс между скоростью контроля остатков и компактностью хранения.
  2. Если количество уникальных номеров исчисляется десятками миллионов и они часто идут подряд — реализуйте логику DIET через индексированные таблицы.
  3. Для задач, где критичен объем дискового пространства, рассмотрите хранение данных в виде сжатых битовых последовательностей в ХранилищеЗначения.

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

← На главную