Почему уникальные идентификаторы (УИД) в 1С генерируются инкрементно

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

При активном создании объектов в платформе 1С разработчики часто замечают, что получаемые уникальные идентификаторы (УИД) генерируются последовательно. Если отсортировать созданные подряд элементы по значению их УИД, они будут выстроены строго в хронологическом порядке. Выясним причины такого поведения платформы, проанализируем внутренние механизмы генерации и разберем, как это влияет на производительность системы управления базами данных (СУБД).

Структура УИД и генерация в рамках сеанса

Рассмотрим, как платформа 1С формирует идентификаторы. В основе алгоритма лежит стандарт RFC 4122 (Version 1, Time-based), который учитывает текущее время и идентификатор узла. Однако platform 1С внесла важную оптимизацию: сервер приложений выдает идентификаторы не по одному, а запрашивает и резервирует их диапазонами (пулами) для каждого конкретного сеанса.

Внутри одного сеанса новые идентификаторы увеличиваются монотонно. Посмотрим на пример последовательно сформированных УИД элементов справочника:

6c7e132d-6c57-11e7-80c6-801844deba29

6c7e132e-6c57-11e7-80c6-801844deba29

6c7e132f-6c57-11e7-80c6-801844deba29

6c7e1330-6c57-11e7-80c6-801844deba29

Разберем по шагам, почему непрерывная последовательность может нарушаться:

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

Перестановка байтов (Byte Swapping) при записи в СУБД

Проанализируем ситуация с хранением данных на уровне базы данных. В СУБД (MS SQL Server, PostgreSQL) ссылочные типы хранятся не в виде текста и не через стандартный тип uniqueidentifier, а в двоичном формате binary(16) (или bytea).

В строковом представлении UUID v1 временная метка разбита на части. Если записать ее в СУБД как есть, инкрементная часть окажется в середине или в конце массива байтов, что сведет на нет всю последовательность при бинарном сравнении. Чтобы решить эту проблему, платформа 1С выполняет перестановку байтов (byte swapping): младшие, быстро меняющиеся временные биты смещаются в начало двоичного массива. Благодаря этому с точки зрения СУБД каждое следующее значение бинарно больше предыдущего.

Влияние последовательных УИД на кластерный индекс СУБД

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

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

  1. Когда целевая страница заполнена, СУБД выполняет операцию Page Split (расщепление страницы): выделяется новая страница, и половина данных переносится туда.
  2. Постоянные расщепления страниц приводят к сильной фрагментации индекса, повышенной нагрузке на диск и задержкам при выполнении транзакций записи (INSERT).
  3. Деградирует скорость чтения данных, так как физическое расположение строк на диске перестает быть последовательным.

Использование инкрементных ключей гарантирует, что новые записи укладываются в самый конец индекса. Страницы заполняются последовательно, расщепления минимальны, а операции ввода-вывода оптимальны.

Практические рекомендации по работе с УИД в 1С

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

  1. Используйте штатные методы создания ссылок: при генерации новых объектов используйте метод ПолучитьСсылку() без передачи собственного УИД, чтобы платформа задействовала оптимальный сеансовый пул:

// Оптимальный способ получения ссылки с последовательным УИД
НоваяСсылка = Справочники.Номенклатура.ПолучитьСсылку();
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.УстановитьСсылкуНового(НоваяСсылка);
  1. Избегайте произвольных UUID (v4) при массовой загрузке: если при загрузке данных из внешних систем передавать случайно сгенерированные УИД (например, UUID v4), это лишит СУБД временной оптимизации и вызовет фрагментацию кластерного индекса.
  2. Настройка СУБД при вынужденном использовании случайных УИД: если специфика интеграции требует сохранения сторонних произвольных GUID, необходимо настроить регулярные регламентные процедуры обслуживания СУБД (дефрагментация и реорганизация индексов), а также уменьшить параметр FILLFACTOR для таблиц с высокой интенсивностью записи.
← На главную