При работе с платформой 1С:Предприятие многие разработчики сталкиваются с ситуацией, когда один и тот же запрос на сервере MS SQL выполняется мгновенно, а в файловом варианте базы (формат 1CD) вызывает полное зависание системы. Особенно часто это проявляется при работе с виртуальными таблицами регистров накопления за длительные периоды. В данной статье мы подробно разберем причины такого поведения и научимся оптимизировать запросы для стабильной работы в любом режиме.
Прежде чем переходить к коду, давайте выясним причину разного поведения СУБД. Промышленная СУБД (например, MS SQL или PostgreSQL) обладает мощным стоимостным оптимизатором. Он анализирует запрос, статистику распределения данных и строит эффективный план выполнения. Файловый движок 1С устроен гораздо проще: он не всегда может эффективно «пробросить» условия внутрь вложенных запросов или оптимизировать сложные соединения. В результате вместо использования индексов система начинает выполнять Full Table Scan — последовательное чтение всей таблицы с диска, что на больших объемах данных приводит к зависанию.
Рассмотрим ситуацию из примера автора. Во втором запросе используется конструкция Заказ В (ВЫБРАТЬ ...) непосредственно в параметрах виртуальной таблицы Обороты. Для файловой базы это «критическое» место. Система может выполнять этот подзапрос многократно для каждой итерации основного цикла обработки данных.
Разберем по шагам правильный подход:
&ПередаваемыеПараметры.Посмотрим на пример правильной структуры:
// Шаг 1: Получаем заказы с остатками во временную таблицу
ВЫБРАТЬ
ЗаказыПокупателейОстатки.Заказ КАК Заказ
ПОМЕСТИТЬ ВТ_ЗаказыСРезервом
ИЗ
РегистрНакопления.ЗаказыПокупателей.Остатки КАК ЗаказыПокупателейОстатки
ГДЕ
ЗаказыПокупателейОстатки.РезервОстаток > 0;
ИНДЕКСИРОВАТЬ ПО
Заказ;
////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Основной запрос с использованием ВТ
ВЫБРАТЬ РАЗРЕШЕННЫЕ
МАКСИМУМ(ЗаказыПокупателейОбороты.Регистратор.Дата) КАК ДатаПост
ИЗ
РегистрНакопления.ЗаказыПокупателей.Обороты(&ДатаНачала, , Регистратор,
СкладКомпании = &СкладКомпании
И Заказ В (ВЫБРАТЬ Заказ ИЗ ВТ_ЗаказыСРезервом)) КАК ЗаказыПокупателейОбороты
// ... дальнейшие условия
В тексте запроса часто встречается обращение ЗаказыПокупателейОбороты.Регистратор.Дата. Проанализируем ситуацию: поле Регистратор является составным типом, который может включать десятки различных документов. Когда вы обращаетесь к Дата через точку, платформа 1С на уровне СУБД создает ЛЕВОЕ СОЕДИНЕНИЕ со всеми таблицами документов, которые могут быть регистраторами этого регистра.
В файловой базе это создает колоссальную нагрузку на дисковую подсистему. Чтобы оптимизировать это, рекомендуется:
Период виртуальной таблицы. В большинстве случаев оно совпадает с датой документа.ССЫЛКА (как в примере автора), но данные старайтесь получать из физической таблицы регистра, если это возможно.Еще одна классическая ошибка — это конструкция РАЗНОСТЬДАТ(ЗаказыПокупателейОбороты.Период, &ТекущаяДата, ДЕНЬ) > 7.
Когда поле Период помещается внутрь функции, СУБД не может использовать индекс по этому полю. Система будет вынуждена прочитать каждую запись, применить к ней функцию и сравнить результат.
Рассмотрим, как это исправить:
Рассчитаем граничную дату заранее в коде на языке 1С и передадим её как готовый параметр. Это позволит системе мгновенно найти нужные записи по индексу.
// В коде 1С:
ГраничнаяДата = ТекущаяДата - (7 * 86400); // 7 дней в секундах
Запрос.УстановитьПараметр("ГраничнаяДата", ГраничнаяДата);
// В тексте запроса:
ГДЕ
ЗаказыПокупателейОбороты.Период < &ГраничнаяДата
Использование РАЗРЕШЕННЫЕ заставляет платформу применять механизмы RLS (Record Level Security). В файловом варианте RLS реализуется путем динамического добавления в ваш запрос множества дополнительных условий и соединений. Если у пользователя настроены сложные права, простой запрос превращается в «монстра» из сотен строк кода SQL.
Совет: При тестировании производительности в файловой базе попробуйте временно запустить запрос под полными правами. Если он отработает быстро — значит, причина в неоптимальных правилах RLS.
Проанализируем и объединим все рекомендации для получения максимально быстрого кода для файловой базы:
РАЗНОСТЬДАТ используем прямое сравнение с параметром.Регистратор.Дата или Номенклатура.Код. Если эти данные нужны, лучше соединить основную таблицу с физической таблицей справочника или документа по ссылке.Регистратор в оборотах. Периодичность День работает значительно быстрее, так как использует таблицы итогов, а не таблицу движений.Соблюдение этих правил позволит вашим отчетам и обработкам работать одинаково быстро как в небольших офисах с файловой базой, так и в крупных корпоративных системах на базе SQL-серверов. Совместное использование временных таблиц и правильных индексов — это ключ к производительности любой системы на платформе 1С.