Как оптимизировать сложные запросы в 1С и ускорить работу системы

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

Проблема производительности запросов — одна из самых актуальных задач для разработчика 1С. Часто мы сталкиваемся с тем, что отчеты или обработки, которые быстро работали на этапе разработки, начинают "тормозить" на реальных данных у заказчика. В данной статье мы подробно разберем методы оптимизации, основываясь на практическом опыте решения проблем с медленными выборками.

Анализируем использование вложенных запросов

Одной из главных причин низкой производительности являются вложенные запросы, особенно те, которые участвуют в соединениях (ЛЕВОЕ СОЕДИНЕНИЕ или ВНУТРЕННЕЕ СОЕДИНЕНИЕ). Когда СУБД встречает вложенный запрос в условии соединения, она зачастую не может эффективно использовать индексы, что приводит к полному сканированию таблиц.

Рассмотрим, как можно улучшить ситуацию. Вместо того чтобы писать вложенный запрос непосредственно в секции соединений, мы рекомендуем использовать временные таблицы. Проанализируем пример кода, который часто вызывает проблемы:


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

Выясним причину, почему это плохо: СУБД вынуждена сначала выполнить вложенный запрос, а затем соединить его результат с основной таблицей без возможности использовать индекс по Номенклатура во временном наборе данных. Чтобы исправить это, разберем по шагам правильный подход с использованием объекта МенеджерВременныхТаблиц.

Работа с временными таблицами и индексация

Для оптимизации мы должны сначала выбрать данные во временную таблицу и обязательно проиндексировать поля, по которым будет происходить соединение. Это позволяет СУБД использовать эффективные алгоритмы поиска (например, Index Seek вместо Scan).

Посмотрим на пример правильной реализации:


// Правильный пример с использованием временной таблицы
ВЫБРАТЬ
    Остатки.Номенклатура КАК Номенклатура,
    Остатки.КоличествоОстаток КАК Остаток
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
;
////////////////////////////////////////////////////////////////////////////////
ИНДЕКСИРОВАТЬ ПО
    Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Продажи.Номенклатура,
    ВТ_Остатки.Остаток
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Остатки КАК ВТ_Остатки
ПО Продажи.Номенклатура = ВТ_Остатки.Номенклатура

Обратите внимание на ключевое слово ИНДЕКСИРОВАТЬ ПО. В 1С 8.3 при создании временной таблицы в одном пакете запроса мы можем сразу указать поля для индексации. Это критически важно для больших объемов данных.

Правила использования виртуальных таблиц

Проанализируем работу с виртуальными таблицами, такими как Остатки, Обороты или СрезПоследних. Распространенной ошибкой является наложение условий на эти таблицы через секцию ГДЕ основного запроса вместо использования параметров самой виртуальной таблицы.

Рассмотрим подробнее: когда вы используете ГДЕ, 1С сначала получает все данные из виртуальной таблицы, и только потом фильтрует их. Если же условие передано в параметры виртуальной таблицы, фильтрация происходит на уровне формирования выборки внутри СУБД, что значительно быстрее.

Пример оптимизации параметров виртуальной таблицы:


// Оптимально: условие в параметрах
ВЫБРАТЬ
    Остатки.КоличествоОстаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Номенклатура = &ВыбраннаяНоменклатура) КАК Остатки

В данном случае система обратится только к нужным записям регистра, используя индекс по измерению Номенклатура.

Использование точек в запросах (обращение через точку)

Еще один важный аспект — обращение к реквизитам через точку от ссылочного поля (например, Продажи.Номенклатура.Артикул). Проанализируем ситуацию: каждое такое обращение в запросе порождает неявное ЛЕВОЕ СОЕДИНЕНИЕ с соответствующей таблицей справочника. Если таких обращений много, структура результирующего SQL-запроса становится крайне громоздкой.

Рекомендация: если вам нужно получить несколько реквизитов одного справочника, лучше один раз явно соединиться с этой таблицей в запросе. Это сделает код прозрачнее и позволит оптимизатору СУБД лучше построить план выполнения.

  1. Всегда проверяйте наличие индексов у полей, которые участвуют в соединениях и условиях ГДЕ.
  2. Избегайте использования функций в условиях запроса (например, НАЧАЛОПЕРИОДА от поля таблицы), так как это отключает использование индекса.
  3. Старайтесь не использовать конструкцию ГДЕ Номенклатура В (ВЫБРАТЬ...). Заменяйте её на ВНУТРЕННЕЕ СОЕДИНЕНИЕ с временной таблицей.
  4. Для проверки эффективности своих решений используйте инструмент "Консоль запросов" с возможностью просмотра плана выполнения SQL.

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

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

← На главную