Как ускорить запросы к полям составного типа в 1С при использовании PostgreSQL?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переходе с MS SQL Server на PostgreSQL многие разработчики 1С сталкиваются с неприятным сюрпризом: запросы, которые раньше работали мгновенно, начинают существенно тормозить. Особенно ярко это проявляется при обращении к полям составного типа «через точку», например, Регистратор.Дата или Владелец.Наименование. В некоторых случаях разница в производительности может достигать 2–3 раз и более. Давайте подробно разберем, почему это происходит, и как мы можем оптимизировать работу системы.

Выясним причину: почему PostgreSQL медленнее MS SQL в таких запросах

Для начала проанализируем ситуацию с точки зрения взаимодействия платформы 1С и СУБД. Когда мы пишем в запросе Регистратор.Дата, система 1С не знает заранее, какой именно документ является регистратором для конкретной записи. Поэтому на уровне SQL-запроса платформа генерирует левое соединение (LEFT JOIN) со всеми таблицами документов, которые теоретически могут быть регистраторами для этого регистра накопления или сведений.

Рассмотрим пример: если у вашего регистра может быть 50 различных типов регистраторов, то в итоговом SQL-запросе, отправляемом к PostgreSQL, будет присутствовать 50 соединений LEFT JOIN. Здесь и кроется корень проблемы. Планировщики разных СУБД обрабатывают такие конструкции по-разному:

Решение 1: Оптимизация запроса с помощью конструкции ВЫРАЗИТЬ

Самый эффективный способ помочь PostgreSQL — это уменьшить количество соединений в запросе. Мы можем явно указать платформе, из какой именно таблицы нужно брать данные. Разберем, как это сделать с помощью оператора ВЫРАЗИТЬ.

Вместо использования прямого обращения:


ВЫБРАТЬ
    Продажи.Регистратор.Дата КАК ДатаРегистратора
ИЗ
    РегистрНакопления.Продажи КАК Продажи

Рассмотрим применение типизации. Если нам заранее известно, что в данной выборке нас интересуют только регистраторы определенного типа (например, «Реализация товаров и услуг»), мы должны написать так:


ВЫБРАТЬ
    ВЫРАЗИТЬ(Продажи.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата КАК ДатаРегистратора
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГДЕ
    Продажи.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг

Почему это работает? В этом случае платформа 1С создаст в SQL-запросе только одно соединение с таблицей документа «Реализация товаров и услуг» вместо нескольких десятков. Для PostgreSQL это на порядок упрощает построение плана выполнения запроса.

Решение 2: Использование ручных соединений в сложных случаях

Бывают ситуации, когда типов регистраторов несколько, но их список ограничен (например, 2 или 3 типа из 50 возможных). В таких случаях мы можем отказаться от обращения «через точку» и выполнить левое соединение самостоятельно. Проанализируем пример такого подхода:


ВЫБРАТЬ
    Взаиморасчеты.Период,
    ЕСТЬNULL(ДокРеализация.Дата, ЕСТЬNULL(ДокАванс.Дата, ДАТАВРЕМЯ(1,1,1))) КАК ДатаДокумента
ИЗ
    РегистрНакопления.Взаиморасчеты КАК Взаиморасчеты
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК ДокРеализация
    ПО Взаиморасчеты.Регистратор = ДокРеализация.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Документ.АвансовыйОтчет КАК ДокАванс
    ПО Взаиморасчеты.Регистратор = ДокАванс.Ссылка

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

Решение 3: Настройка параметров PostgreSQL (Тюнинг СУБД)

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

  1. join_collapse_limit и from_collapse_limit: Эти параметры определяют, при каком количестве таблиц планировщик начнет упрощать поиск плана. По умолчанию в Postgres они часто равны 8. Для работы с 1С рекомендуется увеличить эти значения до 20 или даже 50. Это позволит СУБД дольше искать оптимальный порядок соединения таблиц. Однако помните: слишком высокие значения могут существенно увеличить время планирования запроса (Planning Time).
  2. random_page_cost: Для современных систем на SSD-дисках этот параметр стоит снизить с дефолтных 4.0 до 1.1 или 1.0. Это заставит планировщик чаще отдавать предпочтение использованию индексов (Index Scan) вместо полного сканирования таблиц (Sequential Scan).
  3. effective_cache_size: Убедитесь, что этот параметр установлен корректно (обычно 50-75% от общего объема оперативной памяти). Это помогает оптимизатору понять, какой объем индексов может поместиться в кэш.

Решение 4: Архитектурный подход в метаданных

Посмотрим на проблему шире. Если поле составного типа (например, реквизит в документе) может принимать значения 100 различных типов, это создает нагрузку при любом обращении к этому полю в запросах. Проанализируем структуру ваших данных:

Рекомендуется ограничивать количество типов в свойствах реквизита на этапе проектирования метаданных. Если вы знаете, что в 99% случаев в поле будет храниться ссылка только на 3 вида документов — ограничьте составной тип этими тремя видами. Это автоматически сократит количество генерируемых LEFT JOIN во всех запросах системы, использующих это поле.

Решение 5: Обновление платформы и режима совместимости

Важно отметить, что компания 1С постоянно работает над улучшением взаимодействия с PostgreSQL. Начиная с версий платформы 8.3.20 и выше, были внедрены механизмы оптимизации запросов к составным типам. Платформа стала генерировать более «умные» SQL-конструкции (например, через операторы CASE), которые легче перевариваются планировщиком Postgres.

Важное условие: Эти оптимизации включаются только при использовании соответствующего режима совместимости конфигурации. Если ваша база работает в режиме совместимости с 8.3.14, новые механизмы оптимизации не будут задействованы, даже если вы установите самую свежую версию платформы.

Подводя итог, можно сказать, что медленная работа PostgreSQL с мультитипами — это не приговор, а особенность, требующая более дисциплинированного подхода к написанию запросов. Использование конструкции ВЫРАЗИТЬ и грамотная настройка параметров join_collapse_limit позволяют добиться производительности, сопоставимой с MS SQL Server.

← На главную