При работе с системами маркировки («Честный ЗНАК») и акцизными марками разработчики часто сталкиваются с необходимостью хранения огромных массивов строковых данных. Длина кода маркировки может достигать 150 символов, а их количество в базе — десятков и сотен миллионов записей. Простой поиск по строковому полю в таких условиях неизбежно приводит к деградации производительности и чрезмерному росту размера базы данных. В этой статье мы разберем оптимальные архитектурные подходы для решения этой задачи.
Рассмотрим наиболее надежный вариант структуры данных, который позволяет избежать избыточности и обеспечивает высокую скорость работы. Вместо того чтобы хранить тяжелую строку кода маркировки непосредственно в движениях документов или в основных регистрах, мы разделим данные на две части.
Шаг 1. Создание «легкого» справочника. Создадим справочник (например, ШтрихкодыУпаковок или КодыМаркировки), где единственным значимым реквизитом будет сама строка кода. При этом важно:
Шаг 2. Использование независимого регистра сведений. Для фиксации событий (дата загрузки, база-источник, статус) создадим независимый и неподчиненный РегистрСведений. Первым измерением в нем будет ссылка на наш справочник. Такая структура позволяет параллельно записывать данные и выполнять быстрый поиск по ссылке, которая в SQL представлена компактным типом uniqueidentifier.
Одной из главных проблем при поиске кодов маркировки является их длина. Индекс по строке в 150 символов (300 байт в UTF-16) занимает колоссальный объем места и работает медленно. Проанализируем ситуацию: индекс на 16 байт будет весить в 15-20 раз меньше, чем индекс на полную строку.
Рассмотрим методику поиска через хэш-сумму. Идея заключается в том, чтобы вычислять от длинной строки короткий уникальный отпечаток (хэш) и искать сначала по нему.
Для реализации этого метода:
ХэшПоиска с типом УникальныйИдентификатор.Индексировать.Пример кода для вычисления хэша и записи (с использованием стандартных средств 1С):
Функция ПолучитьХэшМарки(СтрокаМарки)
Хеширование = Новый ХешированиеДанных(АлгоритмХеширования.MD5);
Хеширование.Добавить(СтрокаМарки);
Возврат Новый УникальныйИдентификатор(СтрЗаменить(Строка(Хеширование.ХешСумма), " ", ""));
КонецФункции
// В процедуре ПередЗаписью
ЭтотОбъект.ХэшПоиска = ПолучитьХэшМарки(ЭтотОбъект.ТекстМарки);
Важное замечание: Стандартный объект ХешированиеДанных в 1С может работать медленно на миллионах итераций. Если требуется высокая скорость загрузки, рекомендуется использовать внешнюю компоненту (ВК), которая может вычислять MD5 в 10 раз быстрее.
Выясним причину, почему нельзя полагаться только на хэш или только на поиск по строке в SQL. Коды маркировки чувствительны к регистру (символы 'a' и 'A' — разные), однако большинство баз данных 1С настроены как Case Insensitive (нечувствительные к регистру). Если вы просто выполните запрос ГДЕ ТекстМарки = &Параметр, SQL может вернуть неверный код, отличающийся только регистром.
Проанализируем правильный алгоритм поиска с учетом коллизий хэша и регистра:
ГДЕ указываем проверку по индексируемому полю ХэшПоиска.
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка, ТекстМарки ИЗ Справочник.КодыМаркировки ГДЕ ХэшПоиска = &Хэш";
Запрос.УстановитьПараметр("Хэш", ИскомыйХэш);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Проверка с учетом регистра в 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-хэшу, хранящемуся в поле типа УникальныйИдентификатор. Это обеспечивает баланс между скоростью поиска, размером базы и простотой реализации.