Как реализовать и оптимизировать работу со сверхбольшим справочником на десятки миллионов элементов в 1С?

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

При проектировании учетных систем периодически возникает задача хранения и обработки гигантских массивов нормативно-справочной информации (каталоги автозапчастей, базы материалов, глобальные классификаторы, базы штрихкодов), объем которых составляет десятки и даже сотни миллионов строк. В среде разработчиков существует опасение, что платформа 1С:Предприятие не способна стабильно работать с таблицами свыше 2–3 миллионов записей. Однако под капотом 1С работает полноценная реляционная СУБД (MS SQL Server, PostgreSQL и др.), которая изначально рассчитана на терабайтные массивы. Главная задача разработчика — не допустить неоптимальных конструкций и операций полного сканирования таблицы (Table Scan). Разберем по шагам, как правильно спроектировать работу с такими объемами данных в 1С.

Анализ ограничений платформы и рисков производительности

Для того чтобы система работала стабильно на объемах в 30–100 миллионов записей, выясним причину возможных замедлений и проанализируем критические точки:

  1. Автонумерация и контроль уникальности кода. Стандартный механизм проверки уникальности при записи нового элемента на десятках миллионов строк может вызывать длительные блокировки и медленный поиск максимального кода. Рекомендуется отключать автонумерацию и формировать идентификаторы программно.
  2. Полнотекстовый поиск данных (ППП). Стандартный полнотекстовый поиск платформы создает служебные таблицы колоссального объема. Регламентные задания обновления и слияния индексов на 30+ миллионах строк способны полностью парализовать дисковую подсистему и процессор сервера. Для сверхбольших таблиц полнотекстовый поиск необходимо отключать в свойствах объекта метаданных.
  3. Иерархия элементов и групп. Проверка вхождения в группу с использованием конструкции В ИЕРАРХИИ в запросах строится через рекурсивные алгоритмы или создание временных таблиц. На миллионных выборках это приводит к резкой деградации планов запросов в СУБД. Рекомендуется использовать плоскую структуру справочника, а классификацию выносить в отдельные связующие таблицы.
  4. Поведение динамических списков. Стандартное открытие формы списка с автоподсчетом количества строк и контекстным поиском по неиндексированным полям гарантированно приведет к Table Scan. Форму списка необходимо жестко ограничивать, требуя обязательного указания фильтров перед выводом данных.

Особенности индексации и выбор структуры данных

Проанализируем специфику построения индексов в платформе 1С. В справочниках платформа создает кластерный индекс по ссылке, а также отдельные некластерные индексы по реквизитам, у которых включено свойство Индексировать. Однако создать составной пользовательский индекс по произвольному набору реквизитов в справочнике штатными средствами метаданных невозможно.

Если для бизнес-логики не требуются ссылочные связи внутри других документов, а задача сводится к хранению параметров и быстрому поиску соответствий, отличной альтернативой справочнику является непериодический регистр сведений. В регистрах сведений платформа формирует составной кластерный индекс по измерениям в порядке их следования. Если расположить измерения от наиболее селективного к наименее селективному, СУБД сможет выполнять мгновенный поиск сразу по комбинации ключевых полей (Index Seek).

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

Если справочник все же необходим и требуется производить регулярный быстрый отбор по комбинации 2–3 реквизитов (например, артикул + бренд + код производителя), наиболее эффективным архитектурным приемом является добавление индексированного реквизита-хэша. Рассмотрим пример реализации:

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

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


Процедура ПередЗаписью(Отказ)
    // Нормализуем исходные значения
    ОчищенныйАртикул = ВРег(СокрЛП(СтрЗаменить(Артикул, "-", "")));
    ОчищенныйБренд   = ВРег(СокрЛП(Бренд));
    
    // Формируем составной суррогатный ключ
    КлючПоиска = ОчищенныйБренд + "/" + ОчищенныйАртикул;
КонецПроцедуры

Правила написания запросов: исключение Table Scan

При выборке данных из таблиц объемом более 30 миллионов записей малейшая ошибка в тексте запроса заставит СУБД читать всю таблицу с диска в оперативную память. Разберем правила составления эффективных запросов:

  1. Используйте в условиях ГДЕ только строгие проверки Равно или конструкцию ПОДОБНО с поиском по началу строки (например, &Образец + "%"). Поиск с символом процента в начале строки ("%...") делает использование B-Tree индекса невозможным.
  2. Исключите любые вычисления и функции работы со строками (ПОДСТРОКА, ВЫРАЗИТЬ, функции приведения типов) над полями таблицы в блоке ГДЕ, так как они приводят к вычислению функции для каждой строки таблицы.
  3. Используйте явный отбор первых записей (ВЫБРАТЬ ПЕРВЫЕ N), чтобы ограничить сканирование индекса при совпадении критериев.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 100
    |   Материалы.Ссылка КАК Ссылка,
    |   Материалы.Код КАК Код,
    |   Материалы.Наименование КАК Наименование,
    |   Материалы.Артикул КАК Артикул
    |ИЗ
    |   Справочник.Материалы КАК Материалы
    |ГДЕ
    |   Материалы.КлючПоиска = &КлючПоиска";

Запрос.УстановитьПараметр("КлючПоиска", "BOSCH/0250202022");
Результат = Запрос.Выполнить().Выгрузить();

Использование свойств индексации платформы

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

Внешние источники данных и специализированные поисковые движки

Если бизнес-требования диктуют поиск по неполным совпадениям, подстрокам в середине слов, с учетом опечаток и морфологии, удерживать такие алгоритмы внутри транзакционной СУБД на 30 миллионах записей нецелесообразно. Рассмотрим альтернативные архитектурные пути:

  1. Внешние источники данных (External Data Sources). Таблица выносится в отдельную базу СУБД (например, в отдельную базу MS SQL или PostgreSQL). Это дает возможность вручную создавать сложные покрывающие и фильтрованные составные индексы, настраивать секционирование (partitioning) таблиц и подключать объект в 1С через встроенный механизм внешних источников данных.
  2. Интеграция с поисковыми системами (Elasticsearch, OpenSearch, Manticore Search). Вся номенклатурная масса синхронизируется во внешний поисковый индекс. Пользователь вводит любую строку поиска в интерфейсе 1С, фоновый запрос отправляется через REST/HTTP API в поисковый движок, который за десятки миллисекунд возвращает идентификаторы подходящих строк. Затем 1С выполняет точечную выборку по списку ссылок.

Регламентное обслуживание базы данных

Таблицы размером от 30 миллионов записей крайне чувствительны к состоянию статистики распределения данных. Если статистика устаревает, оптимизатор СУБД ошибочно выбирает неэффективные планы (например, сканирование таблицы вместо поиска по индексу). Для таких справочников необходимо настроить регулярное обновление статистики СУБД (желательно с полным сканированием для ключевых индексов) и периодическую дефрагментацию индексов.

← На главную