Как использовать тип «УникальныйИдентификатор» в больших регистрах сведений 1С и оптимизировать производительность?

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

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

Разберем подробно технические особенности работы платформы 1С и СУБД с уникальными идентификаторами, проанализируем правила индексации и рассмотрим оптимальные архитектурные решения.

Индексирование измерений в регистре сведений: нужно ли ставить флаг?

Рассмотрим, как платформа 1С формирует индексы для независимого регистра сведений. Очень часто разработчики включают свойство Индексировать у единственного или первого измерения регистра, полагая, что это ускорит поиск.

В платформе 1С действует строгое правило формирования структуры таблиц СУБД:

  1. По умолчанию для независимого регистра сведений платформа автоматически создает основной (первичный/кластерный) индекс, в который входят все измерения регистра в порядке их следования в дереве метаданных.
  2. Если измерение является единственным или стоит первым по порядку в списке измерений, дополнительно устанавливать свойство Индексировать не имеет практического смысла. По этому полю поиск и соединения уже будут использовать основной индекс таблицы.
  3. Флаг Индексировать необходим только для тех измерений, которые стоят вторыми и далее в списке измерений, если по ним планируется выполнять частые отборы и поисковые запросы без указания первых измерений.

Сравнение: «УникальныйИдентификатор» против составного ключа «Строка + Число»

Проанализируем две архитектурные модели: использование одного поля типа УникальныйИдентификатор либо пары полей (строковый префикс и порядковый номер).

  1. Размер данных и плотность страниц в кэше: Поле типа УникальныйИдентификатор в СУБД MS SQL физически хранится как бинарное поле binary(16) и занимает ровно 16 байт. Составной ключ из строки (например, NVARCHAR(30), занимающий до 60 байт) и числа (NUMERIC, от 5 до 9 байт) требует значительно больше дискового пространства. Чем компактнее индекс, тем больше строк помещается на одну 8-килобайтную страницу данных в оперативной памяти (Buffer Pool), что напрямую снижает нагрузку на дисковую подсистему ввода-вывода (I/O).
  2. Операции соединения в запросах: Бинарное сравнение 16-байтовых значений на уровне процессора СУБД выполняется быстрее, чем посимвольное сопоставление строк с учетом региональных параметров сортировки (Collation). Кроме того, использование одного поля вместо двух упрощает условия в секции ПО при объединении таблиц в запросах.
  3. Фрагментация страниц при вставке (Page Splits): Это главный фактор риска при работе с GUID. Если значения идентификаторов генерируются внешней системой случайно или формируются через хэш-функции, вставка новых строк в кластерный индекс происходит в произвольные места таблицы. Это вызывает постоянное расщепление страниц данных в MS SQL и деградацию скорости пакетной вставки. Если же идентификаторы формируются монотонно (как стандартные ссылки платформы 1С), новые данные дописываются в конец таблицы без критической фрагментации.

Ограничения платформы 1С при работе с типом «УникальныйИдентификатор»

Выясним, с какими системными особенностями можно столкнуться при использовании типа УникальныйИдентификатор в прикладных решениях:

  1. Работа с временными таблицами в запросах: В версиях платформы ниже 8.3.12 (или при включенном режиме совместимости 8.3.11 и ниже) существовало жесткое ограничение: поля типа УникальныйИдентификатор нельзя было помещать во временные таблицы при передаче таблицы значений в качестве параметра запроса. Начиная с версии платформы 8.3.12.1159, поддержка данного типа была расширена — появилась возможность создавать временные таблицы из таблиц значений с такими колонками и использовать их в условии В.
  2. Пользовательский интерфейс и динамические списки: Для полей типа УникальныйИдентификатор не предусмотрено стандартное пользовательское представление, по ним невозможно настроить полнотекстовый поиск платформы, а стандартная сортировка в запросах упорядочивает их по бинарному значению, а не по алфавиту строкового представления.
  3. Отборы в табличных полях: В некоторых режимах работы форм (особенно на обычных формах) отбор в списке по массиву или списку значений типа УникальныйИдентификатор может быть недоступен программно или интерактивно, в отличие от ссылочных типов.

Оптимизация массовой записи в большие регистры

Если для хранения данных выбран независимый регистр сведений, критически важно правильно реализовать запись. Использование объекта РегистрСведенийМенеджерЗаписи для миллионов строк неприемлемо, так как на каждую строку инициируется отдельное чтение и запись с избыточными блокировками.

Правильный подход — пакетная запись порциями с использованием объекта РегистрСведенийНаборЗаписей:


// Пример пакетной записи набора данных
НаборЗаписей = РегистрыСведений.ИсторияОтправлений.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ИдентификаторОтправления.Установить(Идентификатор);

// Если измерение заведомо уникально и отбор не накладывается на весь регистр,
// выполняем запись без чтения существующих данных порциями
НаборЗаписей.Записывать = Истина;
Для Каждого СтрокаДанных Из МассивНовыхДанных Цикл
    НоваяЗапись = НаборЗаписей.Добавить();
    НоваяЗапись.ИдентификаторОтправления = СтрокаДанных.ГУИД;
    НоваяЗапись.Состояние = СтрокаДанных.Статус;
    НоваяЗапись.ДатаСобытия = СтрокаДанных.Дата;
КонецЦикла;

// Отключаем замещение для прямой вставки новых строк
НаборЗаписей.Записать(Ложь);

Альтернативные архитектурные решения

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

  1. Справочник с табличной частью или подчиненный документ: Объектный подход дает естественную ссылочную целостность, встроенные нумераторы и монотонную генерацию GUID ссылок платформой 1С. Табличные части справочников физически кластеризуются по ссылке владельца и номеру строки, что обеспечивает максимальное быстродействие при получении полной истории по конкретному отправлению.
  2. Разделение данных на «горячие» и «холодные» (Архивирование): Для поддержания высокой производительности рабочая таблица регистра должна содержать только актуальные данные (например, активные отправления за последние 3–6 месяцев). Завершенные операции регламентным заданием переносятся в архивный регистр с аналогичной структурой. В отчетах, где требуется полная история, обращение к обеим таблицам инкапсулируется в общем модуле с помощью конструкции ОБЪЕДИНИТЬ ВСЕ.
← На главную