Почему зависает запрос в файловой базе 1С и как его оптимизировать

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

При работе с платформой 1С:Предприятие многие разработчики сталкиваются с ситуацией, когда один и тот же запрос на сервере MS SQL выполняется мгновенно, а в файловом варианте базы (формат 1CD) вызывает полное зависание системы. Особенно часто это проявляется при работе с виртуальными таблицами регистров накопления за длительные периоды. В данной статье мы подробно разберем причины такого поведения и научимся оптимизировать запросы для стабильной работы в любом режиме.

В чем разница между SQL и файловым движком

Прежде чем переходить к коду, давайте выясним причину разного поведения СУБД. Промышленная СУБД (например, MS SQL или PostgreSQL) обладает мощным стоимостным оптимизатором. Он анализирует запрос, статистику распределения данных и строит эффективный план выполнения. Файловый движок 1С устроен гораздо проще: он не всегда может эффективно «пробросить» условия внутрь вложенных запросов или оптимизировать сложные соединения. В результате вместо использования индексов система начинает выполнять Full Table Scan — последовательное чтение всей таблицы с диска, что на больших объемах данных приводит к зависанию.

Проблема 1: Подзапросы в параметрах виртуальных таблиц

Рассмотрим ситуацию из примера автора. Во втором запросе используется конструкция Заказ В (ВЫБРАТЬ ...) непосредственно в параметрах виртуальной таблицы Обороты. Для файловой базы это «критическое» место. Система может выполнять этот подзапрос многократно для каждой итерации основного цикла обработки данных.

Разберем по шагам правильный подход:

  1. Никогда не используйте вложенные запросы внутри параметров &ПередаваемыеПараметры.
  2. Сначала подготовьте данные во Временной Таблице.
  3. Обязательно проиндексируйте временную таблицу по полям связи.
  4. Используйте временную таблицу в основном запросе.

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


// Шаг 1: Получаем заказы с остатками во временную таблицу
ВЫБРАТЬ
    ЗаказыПокупателейОстатки.Заказ КАК Заказ
ПОМЕСТИТЬ ВТ_ЗаказыСРезервом
ИЗ
    РегистрНакопления.ЗаказыПокупателей.Остатки КАК ЗаказыПокупателейОстатки
ГДЕ
    ЗаказыПокупателейОстатки.РезервОстаток > 0;
    
ИНДЕКСИРОВАТЬ ПО
    Заказ;
////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Основной запрос с использованием ВТ
ВЫБРАТЬ РАЗРЕШЕННЫЕ
    МАКСИМУМ(ЗаказыПокупателейОбороты.Регистратор.Дата) КАК ДатаПост
ИЗ
    РегистрНакопления.ЗаказыПокупателей.Обороты(&ДатаНачала, , Регистратор, 
        СкладКомпании = &СкладКомпании 
        И Заказ В (ВЫБРАТЬ Заказ ИЗ ВТ_ЗаказыСРезервом)) КАК ЗаказыПокупателейОбороты
// ... дальнейшие условия

Проблема 2: Неявные соединения через точку (Регистратор.Дата)

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

В файловой базе это создает колоссальную нагрузку на дисковую подсистему. Чтобы оптимизировать это, рекомендуется:

Проблема 3: Использование функций в секции ГДЕ

Еще одна классическая ошибка — это конструкция РАЗНОСТЬДАТ(ЗаказыПокупателейОбороты.Период, &ТекущаяДата, ДЕНЬ) > 7. Когда поле Период помещается внутрь функции, СУБД не может использовать индекс по этому полю. Система будет вынуждена прочитать каждую запись, применить к ней функцию и сравнить результат.

Рассмотрим, как это исправить:

Рассчитаем граничную дату заранее в коде на языке 1С и передадим её как готовый параметр. Это позволит системе мгновенно найти нужные записи по индексу.


// В коде 1С:
ГраничнаяДата = ТекущаяДата - (7 * 86400); // 7 дней в секундах
Запрос.УстановитьПараметр("ГраничнаяДата", ГраничнаяДата);

// В тексте запроса:
ГДЕ
    ЗаказыПокупателейОбороты.Период < &ГраничнаяДата

Проблема 4: Влияние ключевого слова РАЗРЕШЕННЫЕ

Использование РАЗРЕШЕННЫЕ заставляет платформу применять механизмы RLS (Record Level Security). В файловом варианте RLS реализуется путем динамического добавления в ваш запрос множества дополнительных условий и соединений. Если у пользователя настроены сложные права, простой запрос превращается в «монстра» из сотен строк кода SQL.

Совет: При тестировании производительности в файловой базе попробуйте временно запустить запрос под полными правами. Если он отработает быстро — значит, причина в неоптимальных правилах RLS.

Итоговый алгоритм оптимизации тяжелого запроса

Проанализируем и объединим все рекомендации для получения максимально быстрого кода для файловой базы:

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

Соблюдение этих правил позволит вашим отчетам и обработкам работать одинаково быстро как в небольших офисах с файловой базой, так и в крупных корпоративных системах на базе SQL-серверов. Совместное использование временных таблиц и правильных индексов — это ключ к производительности любой системы на платформе 1С.

← На главную