При анализе структуры базы данных 1С:Предприятие на стороне MS SQL Server многие разработчики задаются вопросом: почему архитекторы платформы отказались от стандартных типов данных, таких как uniqueidentifier или bit, в пользу универсального binary? На первый взгляд это кажется избыточным усложнением, однако за таким решением стоят серьезные архитектурные причины, связанные с производительностью, кроссплатформенностью и историей развития платформы. В этой статье мы подробно разберем, как именно 1С хранит данные на уровне СУБД и какие преимущества это дает.
Разберем ситуацию с типом uniqueidentifier. В MS SQL Server для хранения ссылок 1С использует binary(16). Основная причина кроется в механизме индексации. Стандартные GUID в Windows генерируются не последовательно. Если бы 1С записывала их в базу «как есть» в индексированное поле, это приводило бы к катастрофической фрагментации индексов при каждой вставке новой записи. Новые узлы B-дерева вставлялись бы в случайные места, вызывая постоянную перестройку страниц данных.
Проанализируем решение, которое применила 1С: платформа использует свой собственный алгоритм «переворачивания» байтов GUID. Наиболее часто меняющиеся части идентификатора переносятся в конец последовательности, а более стабильные — в начало. Благодаря этому новые записи в базе данных чаще попадают в конец индекса. Это значительно ускоряет операции записи и снижает нагрузку на дисковую подсистему, так как SQL-серверу не нужно постоянно переупорядочивать данные внутри страниц.
Выясним причину, почему не используется uniqueidentifier с функцией NEWSEQUENTIALID(). Ответ прост: 1С должна обеспечивать идентичное поведение на разных СУБД (PostgreSQL, Oracle, IBM DB2). Реализация собственной логики перестановки байтов на уровне платформы позволяет гарантировать стабильную производительность независимо от того, какой SQL-сервер выбрал клиент.
Рассмотрим, почему для булевых значений часто используется binary(1) вместо стандартного bit. Рассмотрим основные факторы:
0x00 для Ложь и 0x01 для Истина в бинарном поле проще транслировать в запросы, которые поймут и Oracle, и PostgreSQL без специфических диалектов.NULL (за исключением результатов соединений). Поля всегда инициализируются значениями по умолчанию. Использование бинарного типа позволяет платформе жестко контролировать содержимое поля, не полагаясь на особенности обработки NULL конкретной СУБД.Проанализируем ситуацию, когда реквизит имеет составной тип (например, «ДокументОбъект» или «СправочникСсылка»). В этом случае 1С не может создать одну колонку в SQL. Вместо этого создается несколько полей, среди которых обязательно присутствует бинарное «поле типа».
Посмотрим на пример структуры в SQL для составного типа:
_TYPE (бинарное): содержит внутренний код типа метаданных._RRef (ссылка), _N (число), _S (строка) и так далее.Именно по байтовому коду в поле типа платформа понимает, из какой именно параллельной колонки нужно считать данные в конкретный момент. Это позволяет реализовать гибкость метаданных 1С поверх строгой типизации SQL-таблиц.
Долгое время получение GUID напрямую через SQL-запрос было нетривиальной задачей из-за того самого «перевернутого» формата 1С. Однако, начиная с версии платформы 8.3.22, разработчики получили штатный механизм. Теперь нет необходимости вручную переставлять байты с помощью SUBSTRING в прямых SQL-запросах.
Разберем пример кода на языке запросов 1С для получения строкового представления GUID:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
УникальныйИдентификатор(Номенклатура.Ссылка) КАК GUID_Строкой
ИЗ
Справочник.Номенклатура КАК Номенклатура
Платформа автоматически транслирует функцию УникальныйИдентификатор() в соответствующий SQL-код, который учитывает специфику хранения binary(16) и возвращает понятную строку. Это значительно упрощает интеграцию и выгрузку данных во внешние системы.
Важно помнить о поле _Version, которое присутствует почти в каждой объектной таблице. В MS SQL оно имеет тип rowversion (или timestamp), что также является бинарным числом. Платформа использует его для реализации оптимистической блокировки. Перед записью объекта 1С проверяет, не изменилось ли значение _Version в базе данных по сравнению с тем, которое было прочитано при открытии формы. Если значения не совпадают, система выдает ошибку «Данные были изменены или удалены другим пользователем».
Многие задаются вопросом: почему нельзя просто SQL-запросом получить имя таблицы? Дело в том, что соответствие между объектами метаданных (например, Справочник.Контрагенты) и физическими таблицами (например, _Reference42) хранится в системных таблицах Config и DBSchema. Эти данные упакованы во внутренние бинарные форматы (зачастую это сжатые XML-структуры). Платформа расшифровывает их при запуске и кэширует, поэтому прямой доступ к ним через стандартные средства SQL без знания алгоритмов декомпрессии невозможен.
Таким образом, использование типа binary в 1С — это не «квадратные колеса», а выверенное инженерное решение, позволяющее системе оставаться производительной при огромных объемах данных и сохранять независимость от конкретного вендора СУБД.