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