Вопрос об использовании собственных уникальных идентификаторов (GUID) при создании объектов в 1С часто становится предметом споров среди разработчиков. С одной стороны, платформа предоставляет возможность назначить объекту конкретную ссылку, с другой — существуют опасения, что «неродные» идентификаторы могут нарушить внутреннюю логику хранения данных в СУБД и замедлить работу системы. Разберем детально, как устроены ссылки в 1С, как они взаимодействуют с SQL-сервером и к каким реальным последствиям приводит использование произвольных GUID.
Существует мнение, что 1С генерирует идентификаторы строго последовательно (увеличивая значение на +1). Проанализируем это утверждение. На самом деле, платформа использует механизмы операционной системы для получения GUID, но делает это оптимизированно. Рассмотрим, как это происходит на практике.
Платформа 1С запрашивает идентификаторы у ОС не по одному, а определенными блоками (пакетами). В рамках одного рабочего сеанса пользователя генерируемые GUID действительно могут выглядеть упорядоченными. Это можно проверить простым кодом:
Для Итератор = 1 По 10 Цикл
НовыйУИД = Новый УникальныйИдентификатор();
Сообщить(Строка(НовыйУИД));
КонецЦикла;
В результате мы увидим, что идентификаторы меняются лишь в определенных сегментах. Однако при перезапуске сеанса или при работе другого пользователя «точка отсчета» будет иной. Таким образом, строгой глобальной последовательности GUID во всей базе данных не существует. Система изначально спроектирована так, чтобы работать с некоторым разбросом значений, особенно в распределенных информационных базах (РИБ).
Наиболее серьезный технический аргумент против использования случайных GUID связан с тем, как данные физически располагаются на диске. В MS SQL Server таблицы 1С обычно имеют кластерный индекс по полю _IDRRef (которое и является ссылкой). Это означает, что строки в таблице физически отсортированы в соответствии со значением ссылки.
Выясним, что происходит при записи нового объекта:
Когда в заполненной странице не хватает места для новой вставки, происходит расщепление страницы (Page Split). СУБД создает новую страницу, переносит туда половину данных из старой и вставляет новую строку. Рассмотрим последствия этого процесса:
Проанализируем интересную особенность: MS SQL Server при сортировке типа UNIQUEIDENTIFIER ориентируется на последние группы байтов. Платформа 1С «знает» об этом и при записи GUID в базу данных выполняет инверсию байтов. Это делается специально для того, чтобы последовательные с точки зрения логики 1С идентификаторы оставались последовательными для алгоритмов сортировки SQL Server.
Если мы получаем GUID из сторонней системы (например, через API на языке Java или Python), этот идентификатор не учитывает специфику 1С. При массовой загрузке таких данных (миллионы записей) мы гарантированно получим высокую фрагментацию индексов сразу после загрузки.
Многие разработчики считают, что сортировка по ссылке нигде не используется. Однако это не так. Рассмотрим объект МоментВремени, который состоит из даты и ссылки. В задачах, где важна строгая хронология внутри одной секунды (например, при расписании платежей или партионном учете), сравнение двух объектов происходит именно по ссылке.
Если мы генерируем GUID хаотично, то порядок документов, созданных в одну и ту же секунду, станет непредсказуемым. Проанализируем пример:
Момент1 = Новый МоментВремени(ДатаСобытия, Ссылка1);
Момент2 = Новый МоментВремени(ДатаСобытия, Ссылка2);
Если Момент1 < Момент2 Тогда
// Логика зависит от того, какой GUID "меньше"
КонецЕсли;
Хотя для большинства справочников это некритично, для регистров накопления и документов с интенсивным движением это может привести к трудноуловимым логическим ошибкам.
Несмотря на теоретические риски, использование собственных GUID часто является оправданным инструментом для интеграции. Рассмотрим пример синхронизации данных между 1С 7.7 и 1С 8.3. Чтобы избежать создания дублей и лишних таблиц соответствия, можно генерировать GUID в 8-ке на основе уникального ID из 7-ки.
// Пример формирования GUID на основе внешнего ID
Функция СформироватьУИДИзВнешнегоID(ВнешнийID)
// ВнешнийID = "12233445566778899"
СтрокаGUID = "FFFFFFFF-FFFF-FFF1-2233-" + Сред(ВнешнийID, 1, 12);
Возврат Новый УникальныйИдентификатор(СтрокаGUID);
КонецФункции
Такой подход позволяет однозначно сопоставлять объекты в разных базах. Как показывает практика многих разработчиков, для справочников объемом до нескольких сотен тысяч записей негативное влияние на производительность практически незаметно на современном оборудовании (особенно на SSD).
Подведем итог и определим границы применимости «своих» GUID. Использование произвольных идентификаторов не вредит базе данных в плане целостности (ошибок не будет), но требует внимания в следующих случаях:
Если перед нами стоит задача использовать свои идентификаторы, выполним следующие шаги для минимизации проблем:
УстановитьСсылкуНового() перед записью объекта.REORGANIZE или REBUILD).Таким образом, создание элементов по своему GUID — это мощный инструмент интеграции, который при правильном обслуживании базы данных (регулярное обновление статистики и обслуживание индексов) не приносит ощутимого вреда системе.