Как организовать хранение и эффективный поиск миллионов кодов маркировки и акцизных марок в 1С?

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

При работе с системами маркировки («Честный ЗНАК») и акцизными марками разработчики часто сталкиваются с необходимостью хранения огромных массивов строковых данных. Длина кода маркировки может достигать 150 символов, а их количество в базе — десятков и сотен миллионов записей. Простой поиск по строковому полю в таких условиях неизбежно приводит к деградации производительности и чрезмерному росту размера базы данных. В этой статье мы разберем оптимальные архитектурные подходы для решения этой задачи.

Архитектурная схема: Справочник + Регистр сведений

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

Шаг 1. Создание «легкого» справочника. Создадим справочник (например, ШтрихкодыУпаковок или КодыМаркировки), где единственным значимым реквизитом будет сама строка кода. При этом важно:

  1. Отключить индексацию для основного реквизита со строкой (длиной 150 символов), чтобы не раздувать индекс СУБД огромными текстовыми данными.
  2. Использовать этот справочник как «хранилище уникальных строк». Если один и тот же код встречается в разных операциях, в базе будет храниться только одна ссылка.

Шаг 2. Использование независимого регистра сведений. Для фиксации событий (дата загрузки, база-источник, статус) создадим независимый и неподчиненный РегистрСведений. Первым измерением в нем будет ссылка на наш справочник. Такая структура позволяет параллельно записывать данные и выполнять быстрый поиск по ссылке, которая в SQL представлена компактным типом uniqueidentifier.

Использование хэширования для ускорения поиска

Одной из главных проблем при поиске кодов маркировки является их длина. Индекс по строке в 150 символов (300 байт в UTF-16) занимает колоссальный объем места и работает медленно. Проанализируем ситуацию: индекс на 16 байт будет весить в 15-20 раз меньше, чем индекс на полную строку.

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

Для реализации этого метода:

  1. Добавим в справочник реквизит ХэшПоиска с типом УникальныйИдентификатор.
  2. Установим для этого реквизита свойство Индексировать.
  3. При записи кода маркировки будем вычислять MD5-хэш от строки.

Пример кода для вычисления хэша и записи (с использованием стандартных средств 1С):


Функция ПолучитьХэшМарки(СтрокаМарки)
    Хеширование = Новый ХешированиеДанных(АлгоритмХеширования.MD5);
    Хеширование.Добавить(СтрокаМарки);
    Возврат Новый УникальныйИдентификатор(СтрЗаменить(Строка(Хеширование.ХешСумма), " ", ""));
КонецФункции

// В процедуре ПередЗаписью
ЭтотОбъект.ХэшПоиска = ПолучитьХэшМарки(ЭтотОбъект.ТекстМарки);

Важное замечание: Стандартный объект ХешированиеДанных в 1С может работать медленно на миллионах итераций. Если требуется высокая скорость загрузки, рекомендуется использовать внешнюю компоненту (ВК), которая может вычислять MD5 в 10 раз быстрее.

Решение проблемы коллизий и регистра символов

Выясним причину, почему нельзя полагаться только на хэш или только на поиск по строке в SQL. Коды маркировки чувствительны к регистру (символы 'a' и 'A' — разные), однако большинство баз данных 1С настроены как Case Insensitive (нечувствительные к регистру). Если вы просто выполните запрос ГДЕ ТекстМарки = &Параметр, SQL может вернуть неверный код, отличающийся только регистром.

Проанализируем правильный алгоритм поиска с учетом коллизий хэша и регистра:

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

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка, ТекстМарки ИЗ Справочник.КодыМаркировки ГДЕ ХэшПоиска = &Хэш";
Запрос.УстановитьПараметр("Хэш", ИскомыйХэш);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Проверка с учетом регистра в 1С
    Если Выборка.ТекстМарки = ИскомаяМарка Тогда 
        Возврат Выборка.Ссылка;
    КонецЕсли;
КонецЦикла;

Оптимизация хранения на уровне СУБД

Когда объем данных достигает сотен миллионов записей, стоит рассмотреть более глубокие методы оптимизации. Разберем несколько продвинутых техник:

1. Сжатие данных (Compression). Начиная с версии 1С 8.3.23, можно управлять сжатием таблиц на уровне MS SQL Server прямо из консоли управления 1С. Для таблиц с марками рекомендуется использовать Page Compression. Поскольку коды часто имеют одинаковые префиксы (GTIN), сжатие страниц может уменьшить объем занимаемого места на диске в 2-3 раза без заметной потери производительности.

2. Символ GS (Group Separator). Коды DataMatrix содержат спецсимвол ASCII 29. При хранении и поиске важно убедиться, что ваша система нормализует эти символы. Разные сканеры могут передавать его по-разному. Перед расчетом хэша и сохранением строки всегда приводите разделители к единому стандарту, иначе поиск по одной и той же марке не даст результата.

3. Внешние базы данных (ClickHouse). Если ваша задача — только накопление истории и поиск «была ли марка», а не участие в транзакциях 1С, рассмотрите вынос этих данных во внешнюю аналитическую БД, такую как ClickHouse. Она идеально подходит для хранения миллиардов строк, обеспечивает мгновенный поиск и автоматическое сжатие. Связь с 1С в этом случае настраивается через HTTP-запросы (REST API) или внешние источники данных.

Очистка старых данных

Удаление миллионов строк из середины таблицы в MS SQL — это ресурсоемкая операция, которая блокирует таблицу и раздувает лог транзакций. Если вы планируете чистить данные раз в полгода, рассмотрим два варианта:

Подводя итог, наиболее эффективным методом для 1С остается использование независимого регистра сведений с индексацией по MD5-хэшу, хранящемуся в поле типа УникальныйИдентификатор. Это обеспечивает баланс между скоростью поиска, размером базы и простотой реализации.

← На главную