Почему при использовании критерия отбора СвязанныеДокументы возникает ошибка о превышении количества таблиц в запросе?

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

При работе с крупными типовыми конфигурациями на платформе 1С:Предприятие 8.3 (такими как «Бухгалтерия предприятия 3.0») разработчики часто сталкиваются с ситуацией, когда стандартный код, работающий годами, внезапно начинает выдавать ошибку: «Построенный запрос к СУБД использует слишком много таблиц». Эта проблема особенно актуальна при попытке построения дерева подчиненных документов или использовании структуры подчиненности. Разберем детально, почему это происходит, как платформа взаимодействует с базой данных и как исправить ситуацию.

Анализируем исходный код и контекст проблемы

Рассмотрим типовой сценарий, представленный в вопросе. Программист выполняет запрос к объекту метаданных КритерийОтбора.СвязанныеДокументы. Код выглядит следующим образом:


Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Тип.СодержитТип(ТипЗнч(ЗначениеКритерияОтбора)) Тогда
    Возврат Неопределено;
КонецЕсли;

УстановитьПривилегированныйРежим(Истина);

Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|    СвязанныеДокументы.Ссылка
|ИЗ
|    КритерийОтбора.СвязанныеДокументы(&ЗначениеКритерияОтбора) КАК СвязанныеДокументы";

Запрос.УстановитьПараметр("ЗначениеКритерияОтбора", ЗначениеКритерияОтбора);
Возврат Запрос.Выполнить().Выгрузить();

На первый взгляд, код абсолютно корректен. Однако при переносе базы из файлового режима на клиент-серверный вариант (MS SQL Server) выполнение этого фрагмента прерывается системной ошибкой. Проанализируем ситуацию: в файловом режиме лимиты на количество таблиц в запросе практически отсутствуют или обрабатываются внутренним движком 1С иначе, тогда как в SQL-варианте вступают в силу ограничения конкретной СУБД.

Выясняем причину: механизмы работы критериев отбора в SQL

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

На уровне СУБД этот запрос превращается в огромную конструкцию, состоящую из множества операторов UNION ALL. Каждая ветка UNION ALL обращается к отдельной таблице документа, где есть реквизит, входящий в состав данного критерия. Если в конфигурации «Бухгалтерия предприятия 3.0» в критерий СвязанныеДокументы включено, например, 300 различных типов документов, то итоговый SQL-запрос будет пытаться объединить 300 таблиц.

Здесь мы сталкиваемся с жестким ограничением старых версий Microsoft SQL Server. В частности, MS SQL Server 2005 имеет лимит: не более 256 таблиц в одном запросе. Если количество объектов в составе критерия превышает этот лимит, СУБД просто отказывается выполнять запрос.

Разберем пути решения проблемы

Проанализировав ситуацию, мы можем предложить несколько вариантов решения задачи, в зависимости от инфраструктуры и возможности внесения изменений в конфигурацию.

Способ 1. Обновление версии СУБД (Рекомендуемый)

Как было верно замечено в обсуждении, ограничение в 256 таблиц было актуально для SQL Server 2005. Начиная с версии SQL Server 2008 и выше (2012, 2016, 2019 и т.д.), этот лимит был значительно расширен. Теперь он зависит не от фиксированного числа, а от доступной оперативной памяти и сложности дерева плана запроса.

Если ваша организация до сих пор использует сервер 20-летней давности, это становится критическим препятствием для работы современных релизов 1С. Рассмотрим шаги по обновлению:

  1. Выполните полную резервную копию базы данных (dt-файл или средствами SQL).
  2. Установите современную версию MS SQL Server (не ниже 2016) или актуальную версию PostgreSQL, которая также отлично справляется с подобными запросами.
  3. Перенесите базу данных на новый сервер. После этого ошибка исчезнет без изменения программного кода.

Способ 2. Оптимизация состава критерия отбора

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

Посмотрим, что можно сделать:

Способ 3. Программный обход через перебор метаданных

Если мы не хотим менять состав критерия (чтобы не снимать объект с поддержки), мы можем изменить сам алгоритм получения данных. Вместо одного «тяжелого» запроса ко всему критерию, мы можем выполнить серию «легких» запросов к конкретным таблицам документов. Рассмотрим пример реализации такого подхода:


Функция ПолучитьСвязанныеДокументыОптимизировано(ЗначениеКритерия)
    ТаблицаРезультат = Новый ТаблицаЗначений;
    ТаблицаРезультат.Колонки.Добавить("Ссылка");
    
    МетаданныеКритерия = Метаданные.КритерииОтбора.СвязанныеДокументы;
    
    // Перебираем все элементы состава критерия отбора
    Для Каждого ЭлементСостава Из МетаданныеКритерия.Состав Цикл
        
        ИмяПути = ЭлементСостава.ПолноеИмя(); // Например, "Документ.РеализацияТоваровУслуг.Реквизит.Сделка"
        ЧастиПути = СтрРазделить(ИмяПути, ".");
        
        Если ЧастиПути.Количество() < 2 Тогда Продолжить; КонецЕсли;
        
        ИмяТаблицы = ЧастиПути[0] + "." + ЧастиПути[1];
        ИмяРеквизита = ЧастиПути[3];
        
        ЗапросКОбъекту = Новый Запрос;
        ЗапросКОбъекту.Текст = "ВЫБРАТЬ Ссылка ИЗ " + ИмяТаблицы + " ГДЕ " + ИмяРеквизита + " = &Значение";
        ЗапросКОбъекту.УстановитьПараметр("Значение", ЗначениеКритерия);
        
        Выборка = ЗапросКОбъекту.Выполнить().Выбрать();
        Пока Выборка.Следующий() Цикл
            НоваяСтрока = ТаблицаРезультат.Добавить();
            НоваяСтрока.Ссылка = Выборка.Ссылка;
        КонецЦикла;
        
    КонецЦикла;
    
    Возврат ТаблицаРезультат;
КонецФункции

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

Резюме

Подведем итог. Проблема с «лишними таблицами» — это классический конфликт между растущей сложностью современных конфигураций 1С и устаревшей инфраструктурой. Платформа 1С:Предприятие при обращении к КритерийОтбора генерирует сложный SQL-запрос с UNION ALL, число ветвей в котором равно количеству типов документов в критерии. Чтобы избежать ошибок в будущем, наилучшим решением является переход на SQL Server версии 2008 и выше, либо использование PostgreSQL. Программные же методы обхода стоит рассматривать лишь как временную меру до планового обновления серверов.

← На главную