Как оптимизировать запрос динамического списка в 1С при наличии связи один-ко-многим?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При разработке отчетов и доработке интерфейсов в 1С часто возникает задача вывести состояние документа на основе связанных данных. В 1С:Управление торговлей 11 типичным примером является отображение статуса ЗаказаКлиента, зависящего от наличия подчиненного ЗаказаПоставщику. Когда количество документов измеряется тысячами, стандартные решения через ЛЕВОЕ СОЕДИНЕНИЕ в динамическом списке приводят к тому, что система начинает «тормозить», а открытие формы растягивается на долгие минуты. Разберем, как решить эту проблему профессионально.

Почему ваш запрос работает медленно?

Основная причина медленной работы заключается в природе связи между ЗаказомКлиента и ЗаказомПоставщику. Это отношение «один-ко-многим». В обычном запросе, при использовании ЛЕВОГО СОЕДИНЕНИЯ, СУБД вынуждена объединять таблицу заказов с таблицей заказов поставщику, где на один заказ клиента может приходиться несколько записей. Это раздувает объем выборки и требует от SQL-сервера огромных ресурсов для обработки временных таблиц, особенно когда используются ТИПЗНАЧЕНИЯ или сложные условия ВЫБОР КОГДА.

Решение 1: Оптимизация запроса через вложенные подзапросы

Если вы хотите оставить логику в рамках одного запроса, необходимо минимизировать количество соединяемых записей. Вместо того чтобы соединять всю таблицу ЗаказПоставщику целиком, мы сначала получаем список уникальных связей, а затем присоединяем его к основной таблице.

Рассмотрим, как это реализовать:


ВЫБРАТЬ
    Т1.Ссылка,
    НЕ Т2.Ссылка ЕСТЬ NULL КАК ЕстьЗаказПоставщику
ИЗ
    Документ.ЗаказКлиента КАК Т1
ЛЕВОЕ СОЕДИНЕНИЕ 
    (ВЫБРАТЬ 
        Т2.Ссылка, 
        Т2.ДокументОснование 
    ИЗ 
        (ВЫБРАТЬ 
            МАКСИМУМ(Номер) КАК Номер, 
            ДокументОснование 
        ИЗ Документ.ЗаказПоставщику 
        СГРУППИРОВАТЬ ПО ДокументОснование) КАК Т1
    ЛЕВОЕ СОЕДИНЕНИЕ 
        Документ.ЗаказПоставщику КАК Т2 
    ПО 
        Т1.Номер = Т2.Номер 
        И Т1.ДокументОснование = Т2.ДокументОснование) КАК Т2 
ПО 
    Т1.Ссылка = Т2.ДокументОснование

Этот подход позволяет сузить выборку до одной записи для каждого основания, что значительно упрощает работу оптимизатора SQL-запросов.

Решение 2: Архитектурный подход (Регистр сведений)

Если вы работаете в высоконагруженной системе, правильнее всего перенести логику «расчета» из момента отображения списка в момент проведения документов. Создайте РегистрСведений, который будет хранить состояние наличия заказа поставщику.

  1. Создайте независимый или подчиненный регистр сведений, например, СостоянияЗаказовПоставщикам.
  2. Добавьте измерение ЗаказКлиента (тип ДокументСсылка.ЗаказКлиента).
  3. Добавьте ресурс ЕстьЗаказПоставщику (тип Булево).
  4. В процедуре ОбработкаПроведения документов ЗаказПоставщику обновляйте этот регистр.

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

Решение 3: Условное оформление и отложенное получение данных

Иногда возникают ситуации, когда менять структуру метаданных нельзя. В таком случае рассмотрите вариант использования Условного оформления в форме списка. В сам запрос динамического списка вы можете вообще не включать ЗаказПоставщику, а получать информацию о нем только для тех строк, которые в данный момент отображаются на экране пользователя, используя событие ПриПолученииДанных.

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

← На главную