В процессе разработки сложных отчетов на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с проблемой низкой производительности запросов. Одной из наиболее распространенных причин является неправильное обращение к виртуальным таблицам регистров накопления и бухгалтерии. В данной статье мы подробно проанализируем типичные ошибки и разберем по шагам правильные методы оптимизации, предложенные экспертами в сообществе.
Прежде чем переходить к коду, давайте проанализируем ситуацию. Виртуальные таблицы (например, ОстаткиИОбороты) не существуют в базе данных физически. Платформа 1С формирует их «на лету» в момент обращения. Если мы накладываем условия на эти таблицы через конструкцию ГДЕ, система сначала выбирает все записи из регистра, а затем фильтрует их. Это создает колоссальную нагрузку на сервер СУБД.
Рассмотрим пример неоптимального кода:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.КоличествоОборот
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК ПродажиОбороты
ГДЕ
ПродажиОбороты.Номенклатура В (&МассивНоменклатуры)
В данном случае условие ГДЕ заставит систему извлечь все продажи за период, что критично при больших объемах данных.
Первое и самое важное правило — всегда используйте параметры виртуальных таблиц для фильтрации. Давайте посмотрим на пример правильного написания того же запроса:
ВЫБРАТЬ
ПродажиОбороты.Номенклатура,
ПродажиОбороты.КоличествоОборот
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , Номенклатура В (&МассивНоменклатуры)) КАК ПродажиОбороты
В этом варианте 1С передаст условие напрямую в SQL-запрос, и база данных вернет только нужные строки. Это кардинально ускоряет выполнение операции.
Если массив данных для фильтрации (например, список номенклатуры или контрагентов) слишком велик, передача его через параметр может привести к ошибкам переполнения в SQL. В такой ситуации мы рекомендуем использовать объект МенеджерВременныхТаблиц.
Рассмотрим этот метод подробнее:
Проанализируем пример реализации на языке 1С:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВыбраннаяНоменклатура.Ссылка КАК Номенклатура
|ПОМЕСТИТЬ ВТ_Номенклатура
|ИЗ
| &МассивНоменклатуры КАК ВыбраннаяНоменклатура
|;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ПродажиОбороты.Номенклатура,
| ПродажиОбороты.КоличествоОборот
|ИЗ
| РегистрНакопления.Продажи.Обороты(
| &НачалоПериода,
| &КонецПериода, ,
| Номенклатура В (ВЫБРАТЬ Номенклатура ИЗ ВТ_Номенклатура)) КАК ПродажиОбороты";
Запрос.УстановитьПараметр("МассивНоменклатуры", СписокТоваров);
Запрос.УстановитьПараметр("НачалоПериода", ДатаНачала);
Запрос.УстановитьПараметр("КонецПериода", ДатаКонца);
Результат = Запрос.Выполнить();
При использовании виртуальных таблиц часто требуется указать Периодичность (день, месяц, авто). Если вам не нужны детальные данные по дням, всегда указывайте максимально возможный период. Например, если отчет строится за месяц, укажите периодичность Месяц. Это уменьшит количество строк, которые SQL должен сгруппировать, и положительно скажется на скорости формирования отчета.
Также важно помнить об индексах. В виртуальных таблицах остатков платформа автоматически использует индексы по измерениям. Однако, если вы строите запрос по регистру бухгалтерии (Хозрасчетный), обратите внимание на субконто. Обращение к Субконто1 работает быстрее, чем к Субконто2 или Субконто3, из-за структуры индексов в СУБД.
Мы рассмотрели основные методы ускорения работы с данными в 1С. Подведем краткий итог наших действий для оптимизации любого запроса к регистрам:
ГДЕ для фильтрации по измерениям в виртуальных таблицах.Регистр.Остатки(Период, Условие).ВременныеТаблицы с обязательным индексированием.Применение этих простых, но эффективных правил позволит вашим отчетам работать в десятки раз быстрее даже на очень больших информационных базах.