При переходе с MS SQL Server на PostgreSQL многие разработчики 1С сталкиваются с неприятным сюрпризом: запросы, которые раньше работали мгновенно, начинают существенно тормозить. Особенно ярко это проявляется при обращении к полям составного типа «через точку», например, Регистратор.Дата или Владелец.Наименование. В некоторых случаях разница в производительности может достигать 2–3 раз и более. Давайте подробно разберем, почему это происходит, и как мы можем оптимизировать работу системы.
Для начала проанализируем ситуацию с точки зрения взаимодействия платформы 1С и СУБД. Когда мы пишем в запросе Регистратор.Дата, система 1С не знает заранее, какой именно документ является регистратором для конкретной записи. Поэтому на уровне SQL-запроса платформа генерирует левое соединение (LEFT JOIN) со всеми таблицами документов, которые теоретически могут быть регистраторами для этого регистра накопления или сведений.
Рассмотрим пример: если у вашего регистра может быть 50 различных типов регистраторов, то в итоговом SQL-запросе, отправляемом к PostgreSQL, будет присутствовать 50 соединений LEFT JOIN. Здесь и кроется корень проблемы. Планировщики разных СУБД обрабатывают такие конструкции по-разному:
Самый эффективный способ помочь PostgreSQL — это уменьшить количество соединений в запросе. Мы можем явно указать платформе, из какой именно таблицы нужно брать данные. Разберем, как это сделать с помощью оператора ВЫРАЗИТЬ.
Вместо использования прямого обращения:
ВЫБРАТЬ
Продажи.Регистратор.Дата КАК ДатаРегистратора
ИЗ
РегистрНакопления.Продажи КАК Продажи
Рассмотрим применение типизации. Если нам заранее известно, что в данной выборке нас интересуют только регистраторы определенного типа (например, «Реализация товаров и услуг»), мы должны написать так:
ВЫБРАТЬ
ВЫРАЗИТЬ(Продажи.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата КАК ДатаРегистратора
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
Почему это работает? В этом случае платформа 1С создаст в SQL-запросе только одно соединение с таблицей документа «Реализация товаров и услуг» вместо нескольких десятков. Для PostgreSQL это на порядок упрощает построение плана выполнения запроса.
Бывают ситуации, когда типов регистраторов несколько, но их список ограничен (например, 2 или 3 типа из 50 возможных). В таких случаях мы можем отказаться от обращения «через точку» и выполнить левое соединение самостоятельно. Проанализируем пример такого подхода:
ВЫБРАТЬ
Взаиморасчеты.Период,
ЕСТЬNULL(ДокРеализация.Дата, ЕСТЬNULL(ДокАванс.Дата, ДАТАВРЕМЯ(1,1,1))) КАК ДатаДокумента
ИЗ
РегистрНакопления.Взаиморасчеты КАК Взаиморасчеты
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК ДокРеализация
ПО Взаиморасчеты.Регистратор = ДокРеализация.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Документ.АвансовыйОтчет КАК ДокАванс
ПО Взаиморасчеты.Регистратор = ДокАванс.Ссылка
Такой подход позволяет нам полностью контролировать количество соединений в SQL-запросе, не полагаясь на автоматизмы платформы, которые в случае с PostgreSQL могут сработать неоптимально.
Если конфигурация находится «на замке» или переписывать сотни запросов не представляется возможным, следует обратить внимание на настройки самого сервера PostgreSQL. Рассмотрим ключевые параметры, влияющие на планирование запросов с мультитипами:
Посмотрим на проблему шире. Если поле составного типа (например, реквизит в документе) может принимать значения 100 различных типов, это создает нагрузку при любом обращении к этому полю в запросах. Проанализируем структуру ваших данных:
Рекомендуется ограничивать количество типов в свойствах реквизита на этапе проектирования метаданных. Если вы знаете, что в 99% случаев в поле будет храниться ссылка только на 3 вида документов — ограничьте составной тип этими тремя видами. Это автоматически сократит количество генерируемых LEFT JOIN во всех запросах системы, использующих это поле.
Важно отметить, что компания 1С постоянно работает над улучшением взаимодействия с PostgreSQL. Начиная с версий платформы 8.3.20 и выше, были внедрены механизмы оптимизации запросов к составным типам. Платформа стала генерировать более «умные» SQL-конструкции (например, через операторы CASE), которые легче перевариваются планировщиком Postgres.
Важное условие: Эти оптимизации включаются только при использовании соответствующего режима совместимости конфигурации. Если ваша база работает в режиме совместимости с 8.3.14, новые механизмы оптимизации не будут задействованы, даже если вы установите самую свежую версию платформы.
Подводя итог, можно сказать, что медленная работа PostgreSQL с мультитипами — это не приговор, а особенность, требующая более дисциплинированного подхода к написанию запросов. Использование конструкции ВЫРАЗИТЬ и грамотная настройка параметров join_collapse_limit позволяют добиться производительности, сопоставимой с MS SQL Server.