1c recordertref в sql что содержит
Перейти к содержимому

1c recordertref в sql что содержит

  • автор:

Особенность выполнения функции ПОДСТРОКА() языка запросов

Раздел содержит описание особенности выполнения функции ПОДСТРОКА() языка запросов в клиент-серверном варианте работы и вытекающие из нее рекомендации по построению запросов.

Функция ПОДСТРОКА()

В языке запросов 1С:Предприятия функция ПОДСТРОКА() в формате ПОДСТРОКА(, , ) может применяться к данным строкового типа и позволяет выделить фрагмент , начинающийся с символа номер (символы в строке нумеруются с 1) и длиной символов. Результат вычисления функции ПОДСТРОКА() имеет строковый тип переменной длины, причем длина будет считаться неограниченной, если имеет неограниченную длину и параметр не является константой или превышает 1024.

Вычисление функции ПОДСТРОКА() на SQL сервере

В клиент-серверном варианте работы функция ПОДСТРОКА() реализуется при помощи функции SUBSTRING() соответствующего оператора SQL, передаваемого серверу баз данных SQL Server, который вычисляет тип результата функции SUBSTRING() по сложным правилам в зависимости от типа и значений ее параметров, а так же в зависимости от контекста, в котором она используется.

В большинстве случаев эти правила не оказывают влияния на выполнение запроса 1С:Предприятия, однако есть случаи, когда для исполнения запроса существенна максимальная длина строки результата, вычисленная SQL Server. Важно иметь в виду, что в некоторых контекстах использования функции ПОДСТРОКА() максимальная длина ее результата может оказаться равной максимальной длине строки ограниченной длины, которая в SQL Server равна 4000 символам. Это может привести к неожиданному аварийному завершению выполнения запроса.

ВЫБРАТЬ
ВЫБОР
КОГДА Вид = &ЮрАдресФизЛица
ТОГДА ПОДСТРОКА(Представление, 0, 200)
ИНАЧЕ NULL
КОНЕЦ КАК Представление,
ВЫБОР
КОГДА Вид = &ЮрАдресФизЛица
ТОГДА ПОДСТРОКА(Представление, 0, 200)
ИНАЧЕ NULL
КОНЕЦ КАК Представление1
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
УПОРЯДОЧИТЬ ПО
Представление,
Представление1

завершается аварийно с сообщением:

Ошибка СУБД:
Microsoft OLE DB Provider for SQL Server: Warning: The query processor could not produce a query plan from the optimizer because the total length of all the columns in the GROUP BY or ORDER BY clause exceeds 8000 bytes.
HRESULT=80040E14, SQLSTATE=42000, native=8618

Это происходит потому, что вычисленная Microsoft SQL Server максимальная длина строки, которая является результатом выражения:

ВЫБОР
КОГДА Вид = &ЮрАдресФизЛица
ТОГДА ПОДСТРОКА(Представление, 0, 200)
ИНАЧЕ NULL
КОНЕЦ КАК Представление,

равна 4000 символов. Поэтому длина записи, состоящей из двух таких полей превышает 8000 байт, разрешенные для выполнения операции сортировки.

В связи с описанной особенностью исполнения функции SUBSTRING() на SQL Server использование функции ПОДСТРОКА() с целью приведения строк неограниченной длины к строкам ограниченной длины не рекомендуется. Вместо нее лучше использовать операцию приведения типа ВЫРАЗИТЬ() . В частности, приведенный пример можно переписать в виде:

ВЫБРАТЬ
ВЫБОР
КОГДА Вид = &ЮрАдресФизЛица
ТОГДА ВЫРАЗИТЬ(Представление КАК Строка(200))
ИНАЧЕ NULL
КОНЕЦ КАК Представление,
ВЫБОР
КОГДА Вид = &ЮрАдресФизЛица
ТОГДА ВЫРАЗИТЬ(Представление КАК Строка(200))
ИНАЧЕ NULL
КОНЕЦ КАК Представление1
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
УПОРЯДОЧИТЬ ПО
Представление,
Представление1

1c recordertref в sql что содержит

Есть регистр сведений, подчиненный регистратору. Регистратор составной.
Задача — имея Регистратор (ссылку на док) получить значения полей _RecorderTRef и _RecorderRRef для SQL таблицы этого регистра.

_RecorderRRef нашёл как получить — использую ЗначениеВСтрокуВнутр(Ссылка) и вычленяю с 33го символа.
А вот как получить _RecorderTRef пока не нашёл. В строке ЗначениеВСтрокуВнутр(Ссылка) до 33го символа не вижу значений, похожих на то, что в таблице SQL. В строке ЗначениеВСтрокуВнутр(ТипЗнч(Ссылка)) тоже. Методом ПолучитьСтруктуруХраненияБазыДанных() можно получить имена полей SQL, но для типов ничего не нашёл.
Гуглёжь тоже ничего не дал.
Прошу помощи.

п.с. получить на стороне 1С или SQL — без разницы.
cast (123 as bynary) и привет
где 123 — номер документа в структуре хранения
точнее, так
cast(123 as binary(4))

пример _RecorderRRef
не очень на 123 похоже

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

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

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

Многие из объектов метаданных, с которыми работает 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, вносит в выполнение операций сравнения некоторые особенности, понимание и учет которых позволит повысить эффективность разрабатываемых конфигураций.

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

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

                    • все операции сравнения, группировки и упорядочивания, используемые в запросах. В приведенном примере раздел ПО содержит сравнение двух полей на равенство, исполнение которого будет зависеть от типа реквизита «Ответственный» документа «ЗарплатаКВыплате»:

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

                    • преобразования типов и обращения по ссылкам в запросах. В примере значение реквизита Документ.ЗарплатаКВыплате.Ответственный преобразуется к типу «СправочникСсылка.Пользователи» после чего выбирается представление объекта, на который ссылается полученная в результате преобразования ссылка. Реализация преобразования и обращения по ссылке будет зависеть от типа реквизита «Ответственный» документа «ЗарплатаКВыплате».

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

                    • операции сравнения в SQL-запросах, порождаемых различными объектами, встроенными в 1С:Предприятие. Приведенный пример в явном виде запросов не содержит, однако исполнение этого оператора приведет к построению и исполнению SQL-запроса к базе данных, содержащего операции сравнения.

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

                    Сравнение значений во встроенном языке 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

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

                    • к ресурсам регистров и реквизитам, для которых свойство «Индексировать» установлено в «Индексирование» или «Индексировать с доп. упорядочиванием»;
                    • к измерениям регистров (по измерениям регистров индексы создаются автоматически);
                    • к другим полям, участвующим в индексах, согласно разделу ИТС 1С:Предприятия 8.0 «Индексы таблиц базы данных».

                    Функции ВЫРАЗИТЬ и ССЫЛКА в запросах

                    Одна из главных проблем разыменования в запросах является разыменование составных типовых данных. Типичный пример — обращение к полю Регистратор регистра накопления, у которого регистратором является несколько документов.

                    Есть две функции, которые внешне позволяют избежать разыменования — ВЫРАЗИТЬ и ССЫЛКА. Сегодня я продемонстрирую, как они работают со стороны SQL. Для примера была взята СУБД — MS SQL 2014, платформа версии 8.3.10.2580 и конфигурация Комплексная автоматизация.

                    Итак, была взята простейшая выборка — получение поля Дата от Регистратора из регистра накопления ВыручкаИСебестоимостьПродаж. У данного регистра несколько регистраторов, на снимке ниже.

                    ВЫРАЗИТЬ и ССЫЛКА в запросе

                    Первоначально текст запроса следующий:

                    ВЫБРАТЬ ВыручкаИСебестоимостьПродаж.Регистратор.Дата ИЗ РегистрНакопления.ВыручкаИСебестоимостьПродаж КАК ВыручкаИСебестоимостьПродаж ГДЕ ВыручкаИСебестоимостьПродаж.Период МЕЖДУ &НачалоПериода И &КонецПериода

                    При выполнении такого запроса мы получаем следующий запрос на стороне MS SQL

                    exec sp_executesql N'SELECT CASE WHEN T1._RecorderTRef = 0x00000265 THEN T2._Date_Time WHEN T1._RecorderTRef = 0x00000303 THEN T3._Date_Time WHEN T1._RecorderTRef = 0x00000253 THEN T4._Date_Time WHEN T1._RecorderTRef = 0x000002CE THEN T5._Date_Time WHEN T1._RecorderTRef = 0x00000309 THEN T6._Date_Time WHEN T1._RecorderTRef = 0x00000305 THEN T7._Date_Time WHEN T1._RecorderTRef = 0x000002CD THEN T8._Date_Time WHEN T1._RecorderTRef = 0x00000366 THEN T9._Date_Time WHEN T1._RecorderTRef = 0x00000242 THEN T10._Date_Time WHEN T1._RecorderTRef = 0x00000307 THEN T11._Date_Time WHEN T1._RecorderTRef = 0x00000264 THEN T12._Date_Time WHEN T1._RecorderTRef = 0x0000031D THEN T13._Date_Time WHEN T1._RecorderTRef = 0x00000364 THEN T14._Date_Time ELSE CAST(NULL AS DATETIME) END FROM dbo._AccumRg46652 T1 LEFT OUTER JOIN dbo._Document613 T2 ON (T1._RecorderTRef = 0x00000265 AND T1._RecorderRRef = T2._IDRRef) AND (T2._Fld1794 = @P1) LEFT OUTER JOIN dbo._Document771 T3 ON (T1._RecorderTRef = 0x00000303 AND T1._RecorderRRef = T3._IDRRef) AND (T3._Fld1794 = @P2) LEFT OUTER JOIN dbo._Document595 T4 ON (T1._RecorderTRef = 0x00000253 AND T1._RecorderRRef = T4._IDRRef) AND (T4._Fld1794 = @P3) LEFT OUTER JOIN dbo._Document718 T5 ON (T1._RecorderTRef = 0x000002CE AND T1._RecorderRRef = T5._IDRRef) AND (T5._Fld1794 = @P4) LEFT OUTER JOIN dbo._Document777 T6 ON (T1._RecorderTRef = 0x00000309 AND T1._RecorderRRef = T6._IDRRef) AND (T6._Fld1794 = @P5) LEFT OUTER JOIN dbo._Document773 T7 ON (T1._RecorderTRef = 0x00000305 AND T1._RecorderRRef = T7._IDRRef) AND (T7._Fld1794 = @P6) LEFT OUTER JOIN dbo._Document717 T8 ON (T1._RecorderTRef = 0x000002CD AND T1._RecorderRRef = T8._IDRRef) AND (T8._Fld1794 = @P7) LEFT OUTER JOIN dbo._Document870 T9 ON (T1._RecorderTRef = 0x00000366 AND T1._RecorderRRef = T9._IDRRef) AND (T9._Fld1794 = @P8) LEFT OUTER JOIN dbo._Document578 T10 ON (T1._RecorderTRef = 0x00000242 AND T1._RecorderRRef = T10._IDRRef) AND (T10._Fld1794 = @P9) LEFT OUTER JOIN dbo._Document775 T11 ON (T1._RecorderTRef = 0x00000307 AND T1._RecorderRRef = T11._IDRRef) AND (T11._Fld1794 = @P10) LEFT OUTER JOIN dbo._Document612 T12 ON (T1._RecorderTRef = 0x00000264 AND T1._RecorderRRef = T12._IDRRef) AND (T12._Fld1794 = @P11) LEFT OUTER JOIN dbo._Document797 T13 ON (T1._RecorderTRef = 0x0000031D AND T1._RecorderRRef = T13._IDRRef) AND (T13._Fld1794 = @P12) LEFT OUTER JOIN dbo._Document868 T14 ON (T1._RecorderTRef = 0x00000364 AND T1._RecorderRRef = T14._IDRRef) AND (T14._Fld1794 = @P13) WHERE ((T1._Fld1794 = @P14)) AND (((T1._Period >= @P15) AND (T1._Period 
                    

                    Как видим в нем очень много соединений, это все наши документы. Попробуем ограничить выборку, использовав функцию ВЫРАЗИТЬ. Получаем следующий запрос:

                    ВЫБРАТЬ ВЫРАЗИТЬ(ВыручкаИСебестоимостьПродаж.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата КАК Дата ИЗ РегистрНакопления.ВыручкаИСебестоимостьПродаж КАК ВыручкаИСебестоимостьПродаж ГДЕ ВыручкаИСебестоимостьПродаж.Период МЕЖДУ &НачалоПериода И &КонецПериода
                    exec sp_executesql N'SELECT T2._Date_Time FROM dbo._AccumRg46652 T1 LEFT OUTER JOIN dbo._Document870 T2 ON (T1._RecorderTRef = 0x00000366 AND T1._RecorderRRef = T2._IDRRef) AND (T2._Fld1794 = @P1) WHERE ((T1._Fld1794 = @P2)) AND (((T1._Period >= @P3) AND (T1._Period 
                    

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

                    Попробуем наложить отбор в секции ГДЕ с использованием функции ССЫЛКА.

                    ВЫБРАТЬ ВыручкаИСебестоимостьПродаж.Регистратор.Дата КАК Дата ИЗ РегистрНакопления.ВыручкаИСебестоимостьПродаж КАК ВыручкаИСебестоимостьПродаж ГДЕ ВыручкаИСебестоимостьПродаж.Период МЕЖДУ &НачалоПериода И &КонецПериода И ВыручкаИСебестоимостьПродаж.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг

                    На стороне SQL получаем следующую картину:

                    exec sp_executesql N'SELECT CASE WHEN T1._RecorderTRef = 0x00000265 THEN T2._Date_Time WHEN T1._RecorderTRef = 0x00000303 THEN T3._Date_Time WHEN T1._RecorderTRef = 0x00000253 THEN T4._Date_Time WHEN T1._RecorderTRef = 0x000002CE THEN T5._Date_Time WHEN T1._RecorderTRef = 0x00000309 THEN T6._Date_Time WHEN T1._RecorderTRef = 0x00000305 THEN T7._Date_Time WHEN T1._RecorderTRef = 0x000002CD THEN T8._Date_Time WHEN T1._RecorderTRef = 0x00000366 THEN T9._Date_Time WHEN T1._RecorderTRef = 0x00000242 THEN T10._Date_Time WHEN T1._RecorderTRef = 0x00000307 THEN T11._Date_Time WHEN T1._RecorderTRef = 0x00000264 THEN T12._Date_Time WHEN T1._RecorderTRef = 0x0000031D THEN T13._Date_Time WHEN T1._RecorderTRef = 0x00000364 THEN T14._Date_Time ELSE CAST(NULL AS DATETIME) END FROM dbo._AccumRg46652 T1 LEFT OUTER JOIN dbo._Document613 T2 ON (T1._RecorderTRef = 0x00000265 AND T1._RecorderRRef = T2._IDRRef) AND (T2._Fld1794 = @P1) LEFT OUTER JOIN dbo._Document771 T3 ON (T1._RecorderTRef = 0x00000303 AND T1._RecorderRRef = T3._IDRRef) AND (T3._Fld1794 = @P2) LEFT OUTER JOIN dbo._Document595 T4 ON (T1._RecorderTRef = 0x00000253 AND T1._RecorderRRef = T4._IDRRef) AND (T4._Fld1794 = @P3) LEFT OUTER JOIN dbo._Document718 T5 ON (T1._RecorderTRef = 0x000002CE AND T1._RecorderRRef = T5._IDRRef) AND (T5._Fld1794 = @P4) LEFT OUTER JOIN dbo._Document777 T6 ON (T1._RecorderTRef = 0x00000309 AND T1._RecorderRRef = T6._IDRRef) AND (T6._Fld1794 = @P5) LEFT OUTER JOIN dbo._Document773 T7 ON (T1._RecorderTRef = 0x00000305 AND T1._RecorderRRef = T7._IDRRef) AND (T7._Fld1794 = @P6) LEFT OUTER JOIN dbo._Document717 T8 ON (T1._RecorderTRef = 0x000002CD AND T1._RecorderRRef = T8._IDRRef) AND (T8._Fld1794 = @P7) LEFT OUTER JOIN dbo._Document870 T9 ON (T1._RecorderTRef = 0x00000366 AND T1._RecorderRRef = T9._IDRRef) AND (T9._Fld1794 = @P8) LEFT OUTER JOIN dbo._Document578 T10 ON (T1._RecorderTRef = 0x00000242 AND T1._RecorderRRef = T10._IDRRef) AND (T10._Fld1794 = @P9) LEFT OUTER JOIN dbo._Document775 T11 ON (T1._RecorderTRef = 0x00000307 AND T1._RecorderRRef = T11._IDRRef) AND (T11._Fld1794 = @P10) LEFT OUTER JOIN dbo._Document612 T12 ON (T1._RecorderTRef = 0x00000264 AND T1._RecorderRRef = T12._IDRRef) AND (T12._Fld1794 = @P11) LEFT OUTER JOIN dbo._Document797 T13 ON (T1._RecorderTRef = 0x0000031D AND T1._RecorderRRef = T13._IDRRef) AND (T13._Fld1794 = @P12) LEFT OUTER JOIN dbo._Document868 T14 ON (T1._RecorderTRef = 0x00000364 AND T1._RecorderRRef = T14._IDRRef) AND (T14._Fld1794 = @P13) WHERE ((T1._Fld1794 = @P14)) AND (((T1._Period >= @P15) AND (T1._Period 

                    Таким образом можно сделать итог, что использование функции ССЫЛКА в секции ГДЕ на стороне SQL не отсекает лишние соединения и единственное, что может помочь оптимизировать запрос при разыменовании составного типа данных, это функция ВЫРАЗИТЬ. Но ее необходимо использовать с пониманием механизмов на стороне SQL, чтобы не получить нежелательные NULL, либо дополнительно использовать с функцией ССЫЛКА в секции ГДЕ.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *