При работе с системой маркировки «Честный знак» программисты 1С часто сталкиваются с лавинообразным ростом объема данных. Когда количество кодов в регистре сведений исчисляется десятками и сотнями миллионов, стандартные подходы к поиску и записи начинают давать сбой. Рассмотрим, как правильно организовать архитектуру хранения, чтобы база данных не «кряхтела», а поиск оставался мгновенным.
Разберем распространенное заблуждение: «Нельзя делать индекс по уникальным строковым значениям, если их очень много». На самом деле, современные СУБД (MS SQL Server, PostgreSQL), на которых работает 1С, используют структуру B-дерева для индексов. Проанализируем ситуацию: поиск в таблице из 100 000 000 записей по сбалансированному индексу требует всего около 25–30 операций чтения страниц. Это происходит за доли миллисекунды.
Почему же тогда возникают проблемы? Основная причина не в поиске, а в деградации производительности при записи. Коды маркировки — это случайные или слабоупорядоченные строки. При вставке новой записи СУБД должна поместить её в определенное место индекса. Если это место находится в середине уже заполненной страницы данных, происходит «расщепление страницы» (page split). Это тяжелая операция, которая нагружает дисковую подсистему и увеличивает фрагментацию индекса.
Выясним причину избыточности хранения. Полный код маркировки (DataMatrix) содержит в себе GTIN, серийный номер и «криптохвост» (ключ и код проверки). Хранить полную строку длиной более 31 символа (а иногда и до 80+) для каждой операции — это неэффективно.
Проанализируем требования законодательства. Согласно правилам работы с ГИС МТ, участники оборота обязаны удалять крипточасть кода (блоки 91 и 92) после того, как отчет о нанесении или вводе в оборот принят системой. Хранение криптохвостов в основной базе 1С после ввода в оборот не только раздувает индексы, но и может считаться нарушением.
Решение: Разделим код на составляющие. Для уникальной идентификации товара в 99% случаев достаточно связки GTIN (14 цифр) + Серийный номер. Эта связка называется SGTIN. Индексируйте именно эти поля, а не полную строку с криптографическим ключом.
Если специфика задачи всё же требует поиска по длинной строке, рассмотрим вариант с созданием суррогатного ключа или хэш-поля. Идея автора темы с созданием колонки с числом от 1 до 1000 имеет право на жизнь, но диапазон слишком мал — на 100 млн записей мы получим по 100 тысяч коллизий в каждой «корзине».
Посмотрим на пример более эффективного хэширования. Мы можем использовать алгоритм CRC32 или простую комбинацию кодов символов, чтобы получить числовое представление строки. Рассмотрим программную реализацию простого хэш-алгоритма на языке 1С:
Функция ПолучитьХэшКода(Знач ИсходныйКод) Экспорт
Результат = 0;
Для К = 1 По СтрДлина(ИсходныйКод) Цикл
Результат = Результат + КодСимвола(ИсходныйКод, К);
КонецЦикла;
// Берем остаток от деления для получения диапазона,
// например, до 100 000 для уменьшения вероятности коллизий
Возврат Результат % 100000;
КонецФункции
Добавив такое числовое поле в индекс регистра сведений перед основным кодом, мы заставим СУБД сначала искать по числу, что значительно быстрее, чем сравнение длинных строк. Однако помните, что 1С при индексации измерений регистра сведений включает в индекс все измерения, поэтому структура должна быть продуманной.
Рассмотрим предложенный в обсуждении метод «квадратов» для получения равномерного распределения. Это классический метод из теории алгоритмов:
Выделим основные шаги для стабильной работы системы при объемах свыше 10 млн кодов:
ClickHouse. Это колоночная СУБД, которая «проглатывает» миллиарды строк и позволяет искать по ним со скоростью света, не нагружая основную транзакционную базу ERP или УТ.Таким образом, мы выяснили, что бояться больших индексов не стоит, если подходить к их проектированию с умом. Очистка кодов от криптохвостов, переход к хранению SGTIN и правильная настройка СУБД позволяют эффективно работать даже с сотнями миллионов марок честного знака.