Можно ли использовать временные таблицы в динамических списках 1С?

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

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

В чем суть проблемы? Исторический контекст

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

Рассмотрим первый вариант запроса, который отлично работает в обычной консоли запросов:


ВЫБРАТЬ
    УправленческийСубконто.Регистратор КАК Регистратор,
    УправленческийСубконто.НомерСтроки КАК НомерСтроки
ПОМЕСТИТЬ тДвижения
ИЗ
    РегистрБухгалтерии.Управленческий.Субконто КАК УправленческийСубконто
ГДЕ
    УправленческийСубконто.Вид = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконто.Контрагент)
    И УправленческийСубконто.Значение = &Контрагент

ИНДЕКСИРОВАТЬ ПО
    Регистратор,
    НомерСтроки
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    РегистрБухгалтерииУправленческийДвиженияССубконто.Период,
    РегистрБухгалтерииУправленческийДвиженияССубконто.Регистратор,
    РегистрБухгалтерииУправленческийДвиженияССубконто.НомерСтроки,
    РегистрБухгалтерииУправленческийДвиженияССубконто.Активность,
    РегистрБухгалтерииУправленческийДвиженияССубконто.СчетДт,
    РегистрБухгалтерииУправленческийДвиженияССубконто.СубконтоДт1,
    РегистрБухгалтерииУправленческийДвиженияССубконто.Сумма
ИЗ
    РегистрБухгалтерии.Управленческий.ДвиженияССубконто( , , (Регистратор, НомерСтроки) В (ВЫБРАТЬ тДвижения.Регистратор, тДвижения.НомерСтроки ИЗ тДвижения), , ) КАК РегистрБухгалтерииУправленческийДвиженияССубконто

Если мы попытаемся вставить этот пакетный запрос в произвольный запрос динамического списка на платформе версии ниже 8.3.8, то система выдаст ошибку, сообщающую, что поле НомерСтроки или сама временная таблица не найдены. Это происходило из-за технических ограничений платформы: СУБД не могла сериализовать и сохранить МенеджерВременныхТаблиц между вызовами сервера, которые происходят при прокрутке и динамической подгрузке порций данных списка.

Классический обходной путь: Вложенные запросы

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


ВЫБРАТЬ
    РегистрБухгалтерииУправленческийДвиженияССубконто.Период,
    РегистрБухгалтерииУправленческийДвиженияССубконто.Регистратор,
    РегистрБухгалтерииУправленческийДвиженияССубконто.НомерСтроки,
    РегистрБухгалтерииУправленческийДвиженияССубконто.Активность,
    РегистрБухгалтерииУправленческийДвиженияССубконто.СчетДт,
    РегистрБухгалтерииУправленческийДвиженияССубконто.СубконтоДт1,
    РегистрБухгалтерииУправленческийДвиженияССубконто.Сумма
ИЗ
    РегистрБухгалтерии.Управленческий.ДвиженияССубконто( , , (Регистратор, НомерСтроки) В 
        (ВЫБРАТЬ 
            УправленческийСубконто.Регистратор КАК Регистратор, 
            УправленческийСубконто.НомерСтроки КАК НомерСтроки 
         ИЗ 
            РегистрБухгалтерии.Управленческий.Субконто КАК УправленческийСубконто 
         ГДЕ 
            УправленческийСубконто.Вид = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконто.Контрагент) 
            И УправленческийСубконто.Значение = &Контрагент), , ) КАК РегистрБухгалтерииУправленческийДвиженияССубконто

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

Решение проблемы в современных версиях платформы 1С

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

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

  1. В пакетном запросе отсутствуют любые операции (например, принудительное уничтожение временных таблиц через УНИЧТОЖИТЬ или дополнительные выборки) после основного (итогового) запроса пакета.
  2. С момента предыдущего выполнения динамического списка состав временных таблиц и их полей остался абсолютно неизменным.

Ограничения производительности и стандарты разработки «1С»

Несмотря на то, что технически использовать временные таблицы теперь разрешено, стандарты разработки фирмы «1С» (в частности, стандарт #std732) призывают подходить к этому механизму с большой осторожностью. Проанализируем ключевые ограничения производительности:

Практические советы по реализации

Разберем несколько важных технических нюансов, которые помогут вам правильно настроить работу динамического списка с временными таблицами:

1. Специфика визуального конструктора запроса

Если вы откроете стандартный Конструктор запроса из свойств динамического списка в Конфигураторе, вы обнаружите, что вкладка «Пакет запросов» там отсутствует. Чтобы обойти это ограничение, выполните следующие шаги:

  1. Напишите пакетный запрос вручную в текстовом поле динамического списка или скопируйте его из внешней Консоли запросов.
  2. Вставьте готовый текст запроса в поле «Запрос».
  3. После этого откройте Конструктор запроса — он автоматически распознает структуру пакета и отобразит все необходимые вкладки для интерактивного редактирования временных таблиц.

2. Обязательная индексация

При использовании временных таблиц всегда не забывайте индексировать поля связи. Например, если вы соединяете временную таблицу по полям Регистратор и НомерСтроки, обязательно пропишите инструкцию ИНДЕКСИРОВАТЬ ПО Регистратор, НомерСтроки. В противном случае СУБД будет выполнять полное сканирование таблиц (Table Scan) при каждой прокрутке списка, что перегрузит процессор сервера.

3. Особенности работы в среде разработки 1С:EDT

Если вы используете для разработки 1С:EDT (Enterprise Development Tools), будьте осторожны с инструкцией уничтожения временных таблиц в конце пакета. Если в конце вашего запроса будет написано УНИЧТОЖИТЬ тДвижения, EDT потеряет связь с «Основной таблицей» динамического списка. В результате вы не сможете использовать стандартное оформление строк (например, стандартные пиктограммы проведения или удаления документов). Рекомендуется не уничтожать временные таблицы принудительно в тексте запроса динамического списка — платформа сделает это автоматически. Для отладки таких запросов в этой среде подойдет плагин консоли запросов с поддержкой временных таблиц.

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

← На главную