Как ускорить запрос при объединении данных из регистра накопления и документов в 1С

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача получения данных, которые еще не «дошли» до регистров накопления. Типичный пример — отчет по валовой прибыли в ERP, где часть документов реализации (например, товары в пути) отражается в регистре с задержкой, но их данные необходимо включить в отчет уже сейчас по дате самого документа. Рассмотрим, как оптимизировать подобный запрос, если он начинает работать медленно.

Разберем основную причину тормозов: условие «НЕ В»

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

Самым простым и эффективным решением является замена отрицания НЕ В на ЛЕВОЕ СОЕДИНЕНИЕ с последующей проверкой на NULL. Посмотрим на примере, как это выглядит в коде:


// Вместо конструкции ГДЕ НЕ Документ1.Ссылка В (Выбрать Регистратор ИЗ Обороты)
// Используем левое соединение:

ВЫБРАТЬ
    Документ1.Ссылка,
    Документ1.Количество
ИЗ
    ВТ_Документ1 КАК Документ1
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Обороты КАК Обороты
    ПО Документ1.Ссылка = Обороты.Регистратор
ГДЕ
    Обороты.Регистратор ЕСТЬ NULL

Важный момент: использование ЛЕВОЕ СОЕДИНЕНИЕ ... ГДЕ ... ЕСТЬ NULL позволяет SQL-серверу использовать эффективные алгоритмы соединения (например, Hash Match или Merge Join), что ускоряет выполнение запроса в десятки раз.

Оптимизируем работу с виртуальными таблицами

Проанализируем использование виртуальной таблицы РегистрНакопления.Регистр.Обороты(,,Регистратор). Когда мы указываем периодичность Регистратор, платформа 1С перестает использовать таблицы итогов (агрегаты) и начинает выбирать данные напрямую из физической таблицы движений регистра. В этом случае виртуальная таблица становится лишь «оберткой» над тяжелым запросом к основной таблице.

Рассмотрим рекомендации по работе с такими таблицами:

  1. Всегда указывайте период: Если в параметрах виртуальной таблицы не указаны начало и конец периода, система будет сканировать движения регистра с момента «начала времен», что недопустимо для производительности.
  2. Фильтрация по документам: Если вам нужны данные только по конкретным типам документов, лучше использовать физическую таблицу регистра напрямую, наложив фильтр по полю Регистратор ССЫЛКА Документ.ВашТип.
  3. Индексация: Если данные регистра помещаются во временную таблицу, обязательно индексируйте поле Регистратор перед дальнейшими соединениями.

Избавляемся от условий в блоке «ГДЕ», снижающих скорость (SARGability)

Выясним причину, по которой использование конструкции ВЫРАЗИТЬ(Обороты.Регистратор КАК Документ.Документ1).Дата МЕЖДУ &ДатаНачала И &ДатаОкончания в блоке ГДЕ является плохой практикой. С точки зрения SQL-сервера, применение функций (включая приведение типов) к полям индекса делает запрос «не-SARGable». Это означает, что индекс по дате документа не может быть использован, и СУБД переходит к полному сканированию таблицы.

Чтобы избежать этой проблемы, выполним оптимизацию следующим образом:

  1. Сначала отберем ссылки на нужные документы во временную таблицу, используя фильтр по дате документа.
  2. Затем соединим эту временную таблицу с регистром накопления по полю Регистратор.

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


// Шаг 1: Подготовка списка документов с фильтром по дате
ВЫБРАТЬ
    Документ1.Ссылка КАК Ссылка
ПОМЕСТИТЬ ВТ_НужныеДокументы
ИЗ
    Документ.Документ1 КАК Документ1
ГДЕ
    Документ1.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
ИНДЕКСИРОВАТЬ ПО
    Ссылка;

////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Получение оборотов только по отобранным документам
ВЫБРАТЬ
    Регистр.Регистратор,
    Регистр.Количество
ИЗ
    РегистрНакопления.ВашРегистр КАК Регистр
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_НужныеДокументы КАК НужныеДокументы
    ПО Регистр.Регистратор = НужныеДокументы.Ссылка
ГДЕ
    Регистр.Активность = ИСТИНА

Использование системных механизмов ERP/УТ

Для конфигураций на базе ERP 2 и УТ 11 существует специализированный механизм — регистр сведений ДанныеПервичныхДокументов. Посмотрим, почему он может быть полезен. Этот регистр является «плоским» и содержит основные реквизиты всех документов (дату, номер, сумму, ссылку). Обращение к нему происходит значительно быстрее, чем к тяжелым таблицам самих документов (таким как РеализацияТоваровУслуг), которые содержат сотни полей и метаданных.

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

Архитектурный подход: когда запрос бессилен

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

Например, для задачи «товары в пути» можно реализовать следующую логику:

Итоговые рекомендации по оптимизации

Подведем итоги наших изысканий. Для максимально быстрого выполнения запроса придерживайтесь следующей последовательности действий:

  1. Используйте временные таблицы: Разделяйте получение данных из документов и из регистров.
  2. Индексируйте поля связей: Поля Регистратор и Ссылка во временных таблицах должны быть проиндексированы.
  3. Заменяйте «НЕ В» на соединения: Это золотое правило оптимизации 1С для работы с SQL.
  4. Минимизируйте выборку: В таблицы документов (Документ.Документ1.Товары) заходите только после того, как во временной таблице остался минимально необходимый список ссылок.
  5. Учитывайте RLS: Если отчет тормозит только у пользователей с ограниченными правами, рассмотрите возможность выполнения запроса в привилегированном режиме (через вызов серверной процедуры модуля менеджера).

Применение этих методов позволит сократить время формирования отчета с нескольких минут до долей секунды даже на крупных информационных базах.

← На главную