При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с необходимостью выводить сложные, предварительно отфильтрованные данные в динамические списки. Одним из самых мощных инструментов оптимизации запросов в платформе 1С являются временные таблицы. Однако долгое время в среде разработчиков существовало жесткое правило: «Временные таблицы в динамических списках использовать нельзя». В этой статье мы подробно разберем, как обстоят дела на самом деле, как обойти старые ограничения платформы, как использовать временные таблицы в современных версиях 1С и какие подводные камни при этом могут возникнуть.
Разберем классическую ситуацию. Нам необходимо вывести в динамический список все бухгалтерские проводки, в которых участвует определенный контрагент. С точки зрения оптимизации СУБД, правильным подходом будет сначала выбрать все нужные регистраторы и номера строк во временную таблицу, проиндексировать их, а затем соединить с основной таблицей движений регистра бухгалтерии.
Рассмотрим первый вариант запроса, который отлично работает в обычной консоли запросов:
ВЫБРАТЬ
УправленческийСубконто.Регистратор КАК Регистратор,
УправленческийСубконто.НомерСтроки КАК НомерСтроки
ПОМЕСТИТЬ тДвижения
ИЗ
РегистрБухгалтерии.Управленческий.Субконто КАК УправленческийСубконто
ГДЕ
УправленческийСубконто.Вид = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконто.Контрагент)
И УправленческийСубконто.Значение = &Контрагент
ИНДЕКСИРОВАТЬ ПО
Регистратор,
НомерСтроки
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
РегистрБухгалтерииУправленческийДвиженияССубконто.Период,
РегистрБухгалтерииУправленческийДвиженияССубконто.Регистратор,
РегистрБухгалтерииУправленческийДвиженияССубконто.НомерСтроки,
РегистрБухгалтерииУправленческийДвиженияССубконто.Активность,
РегистрБухгалтерииУправленческийДвиженияССубконто.СчетДт,
РегистрБухгалтерииУправленческийДвиженияССубконто.СубконтоДт1,
РегистрБухгалтерииУправленческийДвиженияССубконто.Сумма
ИЗ
РегистрБухгалтерии.Управленческий.ДвиженияССубконто( , , (Регистратор, НомерСтроки) В (ВЫБРАТЬ тДвижения.Регистратор, тДвижения.НомерСтроки ИЗ тДвижения), , ) КАК РегистрБухгалтерииУправленческийДвиженияССубконто
Если мы попытаемся вставить этот пакетный запрос в произвольный запрос динамического списка на платформе версии ниже 8.3.8, то система выдаст ошибку, сообщающую, что поле НомерСтроки или сама временная таблица не найдены. Это происходило из-за технических ограничений платформы: СУБД не могла сериализовать и сохранить МенеджерВременныхТаблиц между вызовами сервера, которые происходят при прокрутке и динамической подгрузке порций данных списка.
Выясним, как разработчики решали эту проблему до появления поддержки временных таблиц. Единственным рабочим вариантом было использование вложенных запросов вместо временных таблиц. Проанализируем измененный запрос:
ВЫБРАТЬ
РегистрБухгалтерииУправленческийДвиженияССубконто.Период,
РегистрБухгалтерииУправленческийДвиженияССубконто.Регистратор,
РегистрБухгалтерииУправленческийДвиженияССубконто.НомерСтроки,
РегистрБухгалтерииУправленческийДвиженияССубконто.Активность,
РегистрБухгалтерииУправленческийДвиженияССубконто.СчетДт,
РегистрБухгалтерииУправленческийДвиженияССубконто.СубконтоДт1,
РегистрБухгалтерииУправленческийДвиженияССубконто.Сумма
ИЗ
РегистрБухгалтерии.Управленческий.ДвиженияССубконто( , , (Регистратор, НомерСтроки) В
(ВЫБРАТЬ
УправленческийСубконто.Регистратор КАК Регистратор,
УправленческийСубконто.НомерСтроки КАК НомерСтроки
ИЗ
РегистрБухгалтерии.Управленческий.Субконто КАК УправленческийСубконто
ГДЕ
УправленческийСубконто.Вид = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконто.Контрагент)
И УправленческийСубконто.Значение = &Контрагент), , ) КАК РегистрБухгалтерииУправленческийДвиженияССубконто
Этот запрос работает без проблем на любых версиях платформы 1С. Однако у него есть существенный недостаток: при больших объемах данных отсутствие индексации во вложенном запросе и невозможность кэширования промежуточных результатов могут привести к серьезному падению производительности СУБД.
Начиная с версии платформы 8.3.8 (при условии, что режим совместимости конфигурации установлен не ниже 8.3.7), разработчики 1С получили долгожданную возможность использовать полноценные пакетные запросы с временными таблицами в динамических списках. Платформа научилась корректно управлять жизненным циклом временных таблиц на уровне СУБД.
Рассмотрим подробнее, как именно платформа оптимизирует работу с временными таблицами в динамическом списке под капотом. Чтобы избежать постоянного пересоздания таблиц при каждом перемещении курсора пользователем, платформа пытается повторно использовать ранее созданные временные таблицы. Это происходит только в том случае, если соблюдаются следующие жесткие условия:
УНИЧТОЖИТЬ или дополнительные выборки) после основного (итогового) запроса пакета.Несмотря на то, что технически использовать временные таблицы теперь разрешено, стандарты разработки фирмы «1С» (в частности, стандарт #std732) призывают подходить к этому механизму с большой осторожностью. Проанализируем ключевые ограничения производительности:
Разберем несколько важных технических нюансов, которые помогут вам правильно настроить работу динамического списка с временными таблицами:
Если вы откроете стандартный Конструктор запроса из свойств динамического списка в Конфигураторе, вы обнаружите, что вкладка «Пакет запросов» там отсутствует. Чтобы обойти это ограничение, выполните следующие шаги:
При использовании временных таблиц всегда не забывайте индексировать поля связи. Например, если вы соединяете временную таблицу по полям Регистратор и НомерСтроки, обязательно пропишите инструкцию ИНДЕКСИРОВАТЬ ПО Регистратор, НомерСтроки. В противном случае СУБД будет выполнять полное сканирование таблиц (Table Scan) при каждой прокрутке списка, что перегрузит процессор сервера.
Если вы используете для разработки 1С:EDT (Enterprise Development Tools), будьте осторожны с инструкцией уничтожения временных таблиц в конце пакета. Если в конце вашего запроса будет написано УНИЧТОЖИТЬ тДвижения, EDT потеряет связь с «Основной таблицей» динамического списка. В результате вы не сможете использовать стандартное оформление строк (например, стандартные пиктограммы проведения или удаления документов). Рекомендуется не уничтожать временные таблицы принудительно в тексте запроса динамического списка — платформа сделает это автоматически. Для отладки таких запросов в этой среде подойдет плагин консоли запросов с поддержкой временных таблиц.
Таким образом, использовать временные таблицы в динамических списках 1С можно и нужно, начиная с версии платформы 8.3.8. Однако всегда сопоставляйте выгоду от использования ВТ с возможными рисками снижения производительности СУБД при больших объемах данных. При необходимости можно использовать другие практические методы добавления полей в динамические списки.