Как исправить ошибку 54000 «число столбцов в соединениях ограничено» при работе с регистром СоответствияОбъектовИнформационныхБаз?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке сложных механизмов интеграции и обмена данными в среде 1С:Предприятие 8.3, особенно при использовании СУБД PostgreSQL, разработчики часто сталкиваются с неочевидной на первый взгляд ошибкой: «ОШИБКА: число столбцов в соединениях ограничено 32767» (SQLSTATE 54000). Эта проблема становится особенно острой при попытке соединить таблицы с использованием полей составного типа, таких как УникальныйИдентификаторИсточника в типовом регистре сведений СоответствияОбъектовИнформационныхБаз.

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

Почему возникает ошибка 54000 и как работает СУБД

Давайте проанализируем ситуацию на уровне взаимодействия платформы 1С и СУБД PostgreSQL. В системе 1С поле составного типа (например, «Любая ссылка» или определяемый тип, включающий сотни объектов) не является одной колонкой в таблице базы данных. Для обеспечения ссылочной целостности и возможности хранения разных типов данных, платформа создает для каждого возможного типа в составе поля две колонки: одну для хранения самого значения (UID ссылки) и одну для идентификатора типа.

Если в вашей конфигурации (например, ERP 2.5 или Комплексная автоматизация) в определяемый тип, используемый в регистре СоответствияОбъектовИнформационныхБаз, включено 500 различных документов и справочников, то одно только это поле порождает в SQL-таблице около 1000 колонок. Когда мы выполняем ЛЕВОЕ СОЕДИНЕНИЕ, PostgreSQL пытается построить виртуальную таблицу результата. Лимит PostgreSQL в 32767 колонок кажется огромным, но при соединении нескольких «тяжелых» таблиц с разветвленными составными типами этот предел легко преодолевается. Платформа 1С при генерации SQL-запроса разворачивает все возможные поля-хранилища, что и приводит к падению запроса еще на этапе планирования в СУБД.

Почему стандартный оператор ВЫРАЗИТЬ перестал помогать?

Рассмотрим пример кода, который часто приводит к ошибке:


ВЫБРАТЬ
    ПроизводствоБезЗаказа.Ссылка КАК ПроизводствоБезЗаказа,
    Соответствия.УникальныйИдентификаторПриемника
ИЗ
    Документ.ПроизводствоБезЗаказа КАК ПроизводствоБезЗаказа
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СоответствияОбъектовИнформационныхБаз КАК Соответствия
        ПО (ПроизводствоБезЗаказа.Ссылка = (ВЫРАЗИТЬ(Соответствия.УникальныйИдентификаторИсточника КАК Документ.ПроизводствоБезЗаказа)))
ГДЕ
    ПроизводствоБезЗаказа.Проведен

Проанализируем ситуацию: разработчик пытается ограничить тип с помощью ВЫРАЗИТЬ непосредственно в условии соединения. Однако в последних версиях платформы (начиная с 8.3.24) логика построения SQL-запросов изменилась. Платформа может сначала сформировать структуру соединения для всей таблицы регистра (со всеми его сотнями колонок), а уже потом пытаться применить фильтр типа. В итоге запрос «взрывается» по количеству колонок до того, как фильтрация вступит в силу.

Решение №1: Использование измерения ТипИсточника

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

Разберем правильный подход с использованием строковой фильтрации:


ВЫБРАТЬ
    Соответствия.УникальныйИдентификаторПриемника,
    Соответствия.УникальныйИдентификаторИсточника
ПОМЕСТИТЬ ВТ_ОтфильтрованныеДанные
ИЗ
    РегистрСведений.СоответствияОбъектовИнформационныхБаз КАК Соответствия
ГДЕ
    Соответствия.ТипИсточника = "ДокументСсылка.ПроизводствоБезЗаказа";

// Теперь соединяем только с узкой временной таблицей
ВЫБРАТЬ
    Производство.Ссылка,
    ВТ.УникальныйИдентификаторПриемника
ИЗ
    Документ.ProductionWithoutOrder КАК Производство
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ОтфильтрованныеДанные КАК ВТ
    ПО Производство.Ссылка = ВТ.УникальныйИдентификаторИсточника

Решение №2: Предварительная типизация через временные таблицы

Если использование строкового поля по каким-то причинам невозможно или неэффективно, мы должны принудительно заставить платформу 1С создать «узкую» таблицу в памяти SQL. Для этого используется помещение данных во временную таблицу с явным приведением типов в списке выбора, а не в условии соединения.

Рассмотрим по шагам этот алгоритм:

  1. Создаем первый запрос пакета, где выбираем только нужные поля из регистра.
  2. В списке ВЫБРАТЬ используем ВЫРАЗИТЬ для каждого составного поля.
  3. В секции ГДЕ ограничиваем выборку через оператор ССЫЛКА.
  4. Помещаем результат во временную таблицу.

Посмотрим на пример реализации:


ВЫБРАТЬ
    ВЫРАЗИТЬ(Соответствия.УникальныйИдентификаторИсточника КАК Документ.ПроизводствоБезЗаказа) КАК ИсточникСсылка,
    Соответствия.УникальныйИдентификаторПриемника КАК ПриемникUID
ПОМЕСТИТЬ ВТ_СоответствияТипизированные
ИЗ
    РегистрСведений.СоответствияОбъектовИнформационныхБаз КАК Соответствия
ГДЕ
    Соответствия.УникальныйИдентификаторИсточника ССЫЛКА Документ.ПроизводствоБезЗаказа;

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

В данном случае во временную таблицу ВТ_СоответствияТипизированные попадут только две колонки на уровне SQL: ссылка на документ ПроизводствоБезЗаказа и идентификатор приемника. Ошибка 54000 гарантированно исчезнет, так как общее количество колонок в соединении будет минимальным.

Решение №3: Оптимизация условий соединения

Выясним еще одну причину возникновения проблемы: обращение через точку к полям составного типа внутри условия ПО. Например, условие ПО Т1.Ссылка = Т2.ПолеСоставногоТипа.Ссылка заставляет платформу выполнять неявное соединение со всеми таблицами, входящими в этот тип.

Для оптимизации рекомендуется использовать следующий синтаксис:


// Вместо прямой связи используем дополнительное условие по типу
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СоответствияОбъектовИнформационныхБаз КАК Соответствия
ПО ПроизводствоБезЗаказа.Ссылка = Соответствия.УникальныйИдентификаторИсточника 
   И Соответствия.УникальныйИдентификаторИсточника ССЫЛКА Документ.ПроизводствоБезЗаказа

Хотя этот метод кажется проще, использование временных таблиц (Решение №2) остается более надежным для высоконагруженных систем на PostgreSQL, так как оно дает более предсказуемый план запроса.

Подведем итоги

Проанализировав проблему, мы можем сделать вывод, что ошибка 54000 — это сигнал о том, что запрос перегружен неявными связями из-за особенностей работы с составными типами в 1С. Чтобы избежать падения системы, придерживайтесь следующих правил:

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

← На главную