Платформа "1С:Предприятие 8"
04.10.2013

Особенности хранения составных типов данных

В этом разделе описаны особенности представления в базе данных полей составных типов и даны рекомендации по их эффективному использованию.

Поля, представляемые в базе данных

Многие из объектов метаданных, с которыми работает 1С:Предприятие 8, определяют таблицы и поля базы данных. Ниже приведен список таких объектов метаданных с указаниями, какие объекты базы данных они определяют:

Подробнее о соответствии таблиц базы данных объектам метаданных описано в разделе "Размещение данных 1С:Предприятия 8". В нем особый интерес представляют те объекты метаданных, которые определяют поля базы данных.

Типы полей и их представление в базе данных

В процессе определения большинства объектов метаданных, определяющих поля базы данных, Конфигуратор предоставляет возможность определения типа данных. Тип данных задает множество значений, которые может принимать это поле. Поскольку типы данных, с которыми работает 1С:Предприятие 8, не всегда имеют точные аналоги в СУБД, для хранения данных в СУБД может быть создано одно или несколько полей в соответствующей таблице базы данных так, чтобы данные могли быть представлены в СУБД наиболее адекватным способом. Остановимся подробнее на правилах построения полей базы данных в зависимости от заданного типа значения объекта метаданных.

Типы данных могут быть простыми и составными. В таблице представлен список простых типов с указанием соответствующего типа поля базы данных в терминах различных серверов баз данных (назначение суффикса см. ниже).

Тип данных Суффикс Тип поля базы данных
MS SQL Server PostgreSQL IBM DB2 Oracle Database
Число: длина n, точность k. нет NUMERIC(n, k) numeric(n, k) dec(n, k) NUMBER(n, k)
Строка фиксированной длины: длина n. нет NCHAR(n) mchar(n) graphic(n) CHAR(n+1)
Строка переменной длины: длина n. нет NVARCHAR(n) mvarchar(n) vargraphic(n) VARCHAR2(n+1)
Строка неограниченной длины. нет NTEXT mvarchar dbclob CLOB
Дата нет DATETIME timestamp timestamp DATE
Булево нет BINARY(1) boolean char(1) for bit data RAW(1)
Хранилище значения нет IMAGE bytea blob BLOB
Ссылка на объекты базы данных одного типа RRef BINARY(16) bytea char(16) for bit data RAW(16)

Наряду с простыми типами могут использоваться и составные типы. Тип поля считается составным, если в Конфигураторе при выборе типа объекта метаданных (реквизита, измерения, ресурса и т.п.) в диалоге редактирования типа данных:

Данные составного типа представляются в базе данных несколькими полями. Все поля базы данных, представляющие один объект метаданных, имеют одинаковые имена, различающиеся суффиксами (несколькими последними символами). Количество и состав полей базы данных определяется выбранной для данного объекта метаданных комбинацией типов. Суффикс имени поля базы данных определяет тип и назначение хранимых в нем данных. В таблице перечислены все возможные суффиксы имен полей базы данных с указанием их типа (в терминах серверов баз данных), назначения полей с этими суффиксами и условия, при которых они добавляются к представлению объектов базы данных данного типа.

Суффикс Тип поля базы данных Поле добавляется в случаях:
MS SQL Server PostgreSQL IBM DB2 Oracle Database
_TYPE BINARY(1) bytea char (1) for bit data RAW(1) - Составной тип объекта метаданных.
Содержит фактический тип хранимого значения.
_L BINARY(1) boolean char (1) for bit data RAW(1) - Выбран тип "Булево".
Содержит значение, если его тип - "Булево", или 0x00 в противном случае.
_N NUMERIC(n,k) numeric(n,k) dec(n,k) NUMBER(n, k) - Выбран тип "Число". Длина - n, точность - k.
Содержит значение, если его тип - "Число", или 0 в противном случае.
_T DATETIME timestamp timestamp DATE - Выбран тип "Дата".
Содержит значение, если его тип - "Дата", или дату 1 января 1 года, 00:00:00.
_S NCHAR(n) mchar(n) graphic(n) CHAR(n+1) - Выбран тип "Строка Фиксированная" длины n символов.
Содержит значение, если его тип - "Строка", или строку из n пробелов в противном случае.
NVARCHAR(n) mvarchar(n) vargraphic(n) VARCHAR2(n+1) - Выбран тип "Строка Переменная" с максимальной длиной n символов.
Содержит значение, если его тип - "Строка", или пустую строку в противном случае.
NTEXT mvarchar dbclob CLOB - Выбран тип "Строка Неограниченная".
Содержит значение, если его тип - "Строка", или пустую строку в противном случае.
_B BINARY(n) bytea char (n) for bit data RAW(n+1) - Может использоваться в служебных полях для хранения двоичных данных длины n байт.
Содержит значение, если его тип "Двоичный" (этот тип является служебным и недоступен на уровне конфигурации), или последовательность нулевых байт в противном случае.
VARBINARY(n) bytea varchar (n) for bit data RAW(n+1) - Может использоваться в служебных полях для хранения двоичных данных с максимальной длиной n байт.
Содержит значение, если его тип "Двоичный" (этот тип является служебным и недоступен на уровне конфигурации), или последовательность байт нулевой длины в противном случае.
IMAGE bytea blob BLOB - Выбран тип "Хранилище значения".
Содержит значение, если его тип "Хранилище значения", или последовательность байт нулевой длины в противном случае.
_RTRef BINARY(4) bytea char (4) for bit data RAW(4) - Выбран тип "Ссылка" на объекты базы данных более чем одного типа.
Содержит номер таблицы, на которую ссылается значение, если его тип "Ссылка", или 0x00000000 в противном случае.
_RRRef BINARY(16) bytea char (16) for bit data RAW(16) - Выбран тип "Ссылка".
Содержит идентификатор записи, на которую ссылается значение, если его тип "Ссылка", или 0x00000000000000000000000000000000 в противном случае.

Перечисленные суффиксы в наименованиях полей и типы полей таблиц базы данных можно заметить, если в клиент-серверном варианте информационной базы посмотреть на структуры создаваемых 1С:Предприятием таблиц при помощи Microsoft SQL Server Enterprise Manager для MS SQL Server (pgAdmin III для PostgreSQL, Центр управления для DB2), или при помощи Microsoft SQL Server Profiler (или аналогичных для PostgreSQL или IBM DB2) посмотреть на SQL запросы, посылаемые Сервером 1С:Предприятия серверу баз данных.

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

В соответствии с приведенными правилами можно выделить следующие варианты представления полями таблиц СУБД полей объектов базы данных 1С:Предприятия:

Выбранная для объекта метаданных комбинация типов.

Набор полей таблицы СУБД, соответствующий полю объекта базы данных 1С:Предприятия.

Выбран один тип, в том числе ссылка на объекты базы данных одного типа. Одно поле (без суффикса или с суффиксом RRef).
Выбрана ссылка на объекты базы данных двух и более типов. Например:
1) СправочникСсылка;
2) СправочникСсылка.Организации, СправочникСсылка.Контрагенты;
3) ЛюбаяСсылка.
Три поля (с суффиксами _TYPE, _RTRef, RRRef).
Выбраны несколько типов, отличных от ссылок, или ссылки с хотя бы одним типом, отличным от ссылок.
Например:
1) Число, строка;
2) Булево, СправочникСсылка.Контрагенты;
3) Число, СправочникСсылка.
Несколько полей (с суффиксами _TYPE и другими).

Варианты перечислены в порядке возрастания ресурсоемкости. Наименее эффективным с точки зрения производительности является последний вариант. Поэтому при его использовании необходимо убедиться, что возможное снижение эффективности существенно не скажется на функционировании конфигурации.

Дополнительные проблемы с производительностью могут возникнуть, если поле, представляемое в СУБД в соответствии с последним вариантом, участвует в индексах (см. "Построение индексов").

Сравнение полей

В процессе функционирования информационных баз одним из важнейших действий над данными является их сравнение. Способ представления в СУБД данных различных типов, реализованный в 1С:Предприятии 8, вносит в выполнение операций сравнения некоторые особенности, понимание и учет которых позволит повысить эффективность разрабатываемых конфигураций.

О каких сравнениях идет речь?

Представление данных в СУБД сказывается на тех сравнениях, которые выполняются средствами СУБД. Среди них:

Копировать в буфер обмена

ВЫБРАТЬ ЗарплатаКВыплате.Представление
ИЗ Документ.ЗарплатаКВыплате КАК ЗарплатаКВыплате
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Пользователи КАК Пользователи
ПО ЗарплатаКВыплате.Ответственный = Пользователи.Ссылка

Копировать в буфер обмена

ВЫБРАТЬ ВЫРАЗИТЬ(ЗарплатаКВыплате.Ответственный КАК Справочник.Пользователи).Представление
ИЗ Документ.ЗарплатаКВыплате КАК ЗарплатаКВыплате

Копировать в буфер обмена

ВыборкаФильтров = Справочники.ФильтрыДляЭлектронныхПисем.Выбрать(, УчетнаяЗапись, Новый Структура("Использование", Истина), "Порядок ВОЗР");

Сравнение значений во встроенном языке 1С:Предприятия не вызывает обращений к СУБД и не зависит от представления в СУБД участвующих в них данных.

Механизм сравнения и замечания по эффективности

Используемые 1С:Предприятием 8 СУБД управляются посредством запросов на языке SQL.

Выбранный в 1С:Предприятии 8 механизм представления данных составных типов позволяет естественным образом исполнять сортировки, группировки и вычисление агрегатных функций в терминах SQL без потери эффективности.

В то же время операции сравнения данных, в представлении которых участвуют несколько полей, для СУБД не являются элементарными и приводят к формированию сложных условий, включающих все поля, которые участвуют в представлении сравниваемых данных. 1С:Предприятие обеспечивает адекватность исполнения любых сравнений данных. Однако игнорирование разработчиком конфигураций ниже следующей информации может привести к снижению эффективности разрабатываемых конфигураций.

Методику сравнения полей составных типов поясним на примере. Пусть в конфигурации, например, у документов, определены реквизиты "Реквизит1" и "Реквизит2". В базе данных этим реквизитам будут соответствовать поля, имена которых генерируются конфигуратором. Пусть конфигуратор реквизиту "Реквизит1" поставил в соответствие поля базы данных с префиксом _Fld1, а реквизиту "Реквизит2" - с префиксом _Fld2. Несколько вариантов сравнений реквизитов "Реквизит1" и "Реквизит2" составных типов средствами SQL приведены в таблице:

Операция сравнения.

Реализация средствами SQL.

Реквизит1 = Реквизит2 _Fld1_TYPE = _Fld2_TYPE AND (
_Fld1_TYPE = 0x01 OR
_Fld1_TYPE = 0x02 AND _Fld1_L = _Fld2_L OR
_Fld1_TYPE = 0x03 AND _Fld1_N = _Fld2_N OR
_Fld1_TYPE = 0x04 AND _Fld1_T = _Fld2_T OR
_Fld1_TYPE = 0x05 AND _Fld1_S = _Fld2_S OR
_Fld1_TYPE = 0x06 AND _Fld1_B = _Fld2_B OR
_Fld1_TYPE = 0x07 AND _Fld1_RTRef = _Fld2_RTRef AND _Fld1_RRRef = _Fld2_RRRef)
Реквизит1 <> Реквизит2 _Fld1_TYPE <> _Fld2_TYPE OR (
_Fld1_TYPE = 0x02 AND _Fld1_L <> _Fld2_L OR
_Fld1_TYPE = 0x03 AND _Fld1_N <> _Fld2_N OR
_Fld1_TYPE = 0x04 AND _Fld1_T <> _Fld2_T OR
_Fld1_TYPE = 0x05 AND _Fld1_S <> _Fld2_S OR
_Fld1_TYPE = 0x06 AND _Fld1_B <> _Fld2_B OR
_Fld1_TYPE = 0x07 AND (_Fld1_RTRef <> _Fld2_RTRef OR _Fld1_RRRef <> _Fld2_RRRef)
Реквизит1 > Реквизит2 _Fld1_TYPE > _Fld2_TYPE OR _Fld1_TYPE = _Fld2_TYPE AND (
_Fld1_TYPE = 0x02 AND _Fld1_L > _Fld2_L OR
_Fld1_TYPE = 0x03 AND _Fld1_N > _Fld2_N OR
_Fld1_TYPE = 0x04 AND _Fld1_T > _Fld2_T OR
_Fld1_TYPE = 0x05 AND _Fld1_S > _Fld2_S OR
_Fld1_TYPE = 0x06 AND _Fld1_B > _Fld2_B OR
_Fld1_TYPE = 0x07 AND (_Fld1_RTRef > _Fld2_RTRef OR _Fld1_RTRef = _Fld2_RTRef AND _Fld1_RRRef > _Fld2_RRRef))

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

Особым случаем сравнения полей составных типов являются те сравнения, в реализации которых средствами SQL операция OR не используется. Исполнение таких сравнений не может привести к существенному снижению производительности. Среди них:

Реализация следующих сравнений хотя и может содержать операции OR, но, как правило, хорошо оптимизируется СУБД. Их исполнение обычно также не приводит к существенному снижению производительности.

Приведенные выше соображения позволяют сформулировать следующие рекомендации по использованию полей составных типов:

Копировать в буфер обмена

ВЫБРАТЬ ПриходнаяНакладная.Контракт
ИЗ Документ.ПриходнаяНакладная КАК ПриходнаяНакладная
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РасходнаяНакладная КАК РасходнаяНакладная
ПО ПриходнаяНакладная.Контракт = РасходнаяНакладная.Контракт

Построение индексов

Особое внимание при использовании составных типов следует уделить проблемам, связанным с построением индексов базы данных. В 1С:Предприятии 8 индексы создаются автоматически при создании объектов метаданных по правилам, подробно описанным в следующих разделах ИТС 1С:Предприятия 8.0:

Создание индексов по полям составных типов имеет важную особенность.

Если в индекс входит поле составного типа, для которого задано несколько различных типов (отличных от ссылок, или ссылки с хотя бы одним типом, отличным от ссылок), то вместо каждого индекса, включающего это поле, будет создано столько индексов, сколько различных типов содержится в описании типа этого поля. Это позволяет уменьшить длину ключа в индексе и использовать построенные индексы в операциях сравнения полей составных типов.

Например, если тип поля "Реквизит1" включает типы "Число", "Дата", "СправочникСсылка.Контрагенты", и это поле участвует в индексе, то фактически будет создано 3 индекса, в которые входят следующие наборы полей базы данных:

1) _Fld1_TYPE, _Fld1_N
2) _Fld1_TYPE, _Fld1_D
3) _Fld1_TYPE, _Fld1_RRRef

где "_Fld1" - пример образа объекта метаданных "Реквизит1" в базе данных.

Еще пример. Пусть поле "Реквизит1" включает типы "Булево", "Число", "СправочникСсылка.Контрагенты", "СправочникСсылка.Номенклатура", "СправочникСсылка.Валюты". Будут созданы следующие 3 индекса:

1) _Fld1_TYPE, _Fld1_L
2) _Fld1_TYPE, _Fld1_N
3) _Fld1_TYPE, _Fld1_RTRef, _Fld1_RRRef

Важно иметь в виду, что если в индекс входят несколько полей составных типов, то количество фактически созданных индексов будет равно произведению количеств различных типов (здесь ссылки считаются одним типом), составляющих тип каждого из полей. Таким образом, неосторожное использование индексируемых полей составных типов может привести к построению чрезмерно большого количества индексов, что может отрицательно сказаться на производительности и ресурсоемкости информационной базы. Это в первую очередь относится: