При разработке конфигураций на платформе 1С:Предприятие 8 мы часто сталкиваемся с необходимостью вывода дополнительных данных в списки документов. В типовых конфигурациях, таких как Зарплата и Управление Персоналом, нередко можно встретить конструкции, где внутри поля выборки запроса размещается вложенный подзапрос. Давайте разберем, насколько это эффективно, как это работает на уровне СУБД и стоит ли опасаться снижения производительности.
В примере из темы мы видим конструкцию, которая проверяет наличие записи в регистре сведений для каждой строки основного списка:
ВЫБОР
КОГДА ИСТИНА В
(ВЫБРАТЬ ПЕРВЫЕ 1
ИСТИНА
ИЗ
РегистрСведений.ОплатаВедомостейНаВыплатуЗарплаты КАК ОплатаВедомостейНаВыплатуЗарплаты
ГДЕ
ОплатаВедомостейНаВыплатуЗарплаты.Ведомость = ЖурналДокументовВедомостиНаВыплатуЗарплаты.Ссылка)
ТОГДА ИСТИНА
ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК ЕстьОплаты
На первый взгляд кажется, что для каждой строки списка сервер будет выполнять отдельный запрос к таблице регистра, что может привести к катастрофическому замедлению. Однако важно понимать, что современные оптимизаторы SQL (например, MS SQL Server) обладают достаточным уровнем «интеллекта», чтобы оптимизировать подобные конструкции.
В подавляющем большинстве случаев оптимизатор СУБД не выполняет подзапрос «в лоб» для каждой строки. Вместо этого он преобразует коррелированный запрос в более эффективную операцию соединения, такую как Left Semi Join или Left Anti Semi Join. Это позволяет серверу обрабатывать данные наборами, а не итеративно.
Тем не менее, для того чтобы эта магия оптимизации сработала, должны соблюдаться определенные условия:
Ведомость в таблице РегистрСведений.ОплатаВедомостейНаВыплатуЗарплаты обязательно должно быть проиндексировано. Если индекс отсутствует, SQL-сервер будет вынужден выполнять полное сканирование таблицы (Table Scan) для каждой строки, что мгновенно сделает интерфейс «неотзывчивым».ПЕРВЫЕ 1 внутри подзапроса помогает оптимизатору понять, что нам не нужно выбирать все записи, а достаточно найти лишь первый факт соответствия. Это позволяет прекратить поиск сразу после обнаружения первой записи.Несмотря на то, что использование подзапросов в поле выборки является допустимым приемом, существуют ситуации, когда от них лучше отказаться в пользу других архитектурных решений:
Если вы столкнулись с медленной работой динамического списка, мы рекомендуем выполнить следующие шаги:
SQL Server Management Studio) для анализа плана выполнения. Если вы видите операцию Table Scan или Clustered Index Scan на большой таблице, это прямой сигнал к необходимости создания индекса.ВременныеТаблицы, проиндексируйте их, и выполните итоговое соединение с основной таблицей. Это дает СУБД наиболее точное понимание структуры данных и позволяет построить оптимальный план выполнения.Подводя итог: использование подзапросов в полях выборки — это стандартный инструмент разработчика 1С. В типовых конфигурациях он используется повсеместно и, как правило, хорошо оптимизирован. Главное — помнить об индексах и не злоупотреблять тяжелыми операциями внутри таких подзапросов. Если же производительность все-таки вызывает нарекания, временные таблицы всегда придут на помощь.