При активном создании объектов в платформе 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
Разберем по шагам, почему непрерывная последовательность может нарушаться:
Проанализируем ситуация с хранением данных на уровне базы данных. В СУБД (MS SQL Server, PostgreSQL) ссылочные типы хранятся не в виде текста и не через стандартный тип uniqueidentifier, а в двоичном формате binary(16) (или bytea).
В строковом представлении UUID v1 временная метка разбита на части. Если записать ее в СУБД как есть, инкрементная часть окажется в середине или в конце массива байтов, что сведет на нет всю последовательность при бинарном сравнении. Чтобы решить эту проблему, платформа 1С выполняет перестановку байтов (byte swapping): младшие, быстро меняющиеся временные биты смещаются в начало двоичного массива. Благодаря этому с точки зрения СУБД каждое следующее значение бинарно больше предыдущего.
Выясним главную причину, почему платформа стремится обеспечивать инкрементность УИД. Это связано с устройством B-Tree (сбалансированного дерева) кластерных индексов в СУБД.
Кластерный индекс определяет физический порядок хранения строк на диске. Если новые записи добавляются с произвольными (случайными) ключами, СУБД вынуждена вставлять их в произвольные страницы индекса:
INSERT).Использование инкрементных ключей гарантирует, что новые записи укладываются в самый конец индекса. Страницы заполняются последовательно, расщепления минимальны, а операции ввода-вывода оптимальны.
Разберем основные правила, которых следует придерживаться при программном создании объектов и интеграциях со сторонними системами:
ПолучитьСсылку() без передачи собственного УИД, чтобы платформа задействовала оптимальный сеансовый пул:
// Оптимальный способ получения ссылки с последовательным УИД
НоваяСсылка = Справочники.Номенклатура.ПолучитьСсылку();
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.УстановитьСсылкуНового(НоваяСсылка);
FILLFACTOR для таблиц с высокой интенсивностью записи.