Многие пользователи и администраторы системы 1С:Управление торговлей редакции 11.5 после обновления или при накоплении данных в базе сталкиваются с неприятной проблемой: формирование стандартной печатной формы из документа Установка цен номенклатуры начинает занимать аномально много времени — от нескольких минут до десяти и более. При этом количество строк в самом документе может быть незначительным (всего 10–20 позиций), а база данных может работать в файловом режиме.
В данной статье мы подробно разберем, почему это происходит, как провести диагностику и какими способами можно ускорить вывод на печать, исправив ошибки в типовом коде или настройках системы.
Для начала проанализируем ситуацию. Если печатная форма выводится долго, нам необходимо понять, на каком именно этапе происходит задержка: во время выполнения запроса к базе данных или непосредственно при отрисовке табличного документа на экране. Для этого воспользуемся встроенным инструментом Замер производительности (Отладка — Замер производительности).
Рассмотрим результаты замера. Как показывает практика, в 99% случаев основное время выполнения (более 90%) приходится на одну строку кода в модуле менеджера документа или специализированном модуле печати:
РезультатЗапроса = Запрос.ВыполнитьПакет();
Это однозначно говорит нам о том, что проблема кроется в неоптимальном запросе, который формирует данные для печатной формы. Даже если строк в документе мало, движок базы данных тратит колоссальное время на обработку этого запроса.
Разберем по шагам, что именно в тексте запроса заставляет систему «задумываться». В типовых конфигурациях УТ 11.5 (особенно в релизах ветки 11.5.7) в процедуре СформироватьПечатнуюФормуУстановкиЦенНоменклатуры используется пакетный запрос. Проанализируем его критическую часть, отвечающую за получение действующих цен (старых цен) для сравнения с новыми.
Проблема заключается в конструкции обращения к виртуальной таблице СрезПоследних регистра сведений ЦеныНоменклатуры. Рассмотрим фрагмент «проблемного» кода:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаСреза,
(Номенклатура, Характеристика, ВидЦены) В (
ВЫБРАТЬ
Т.Номенклатура,
Т.Характеристика,
Т.ВидЦены
ИЗ
Документ.УстановкаЦенНоменклатуры.Товары КАК Т
)
) КАК ЦеныНоменклатурыСрезПоследних
Выясним причину замедления. В параметре условия виртуальной таблицы (второй параметр функции СрезПоследних) используется вложенный запрос к табличной части документа УстановкаЦенНоменклатуры.Товары. Внимание: в этом вложенном запросе отсутствует фильтр по конкретной ссылке на текущий документ! Это означает, что для получения цен по десяти позициям текущего документа система заставляет SQL-сервер (или движок файловой базы) просканировать табличные части всех документов установки цен, когда-либо созданных в базе.
Если в базе накоплено много документов, общее количество строк в табличных частях которых исчисляется сотнями тысяч или миллионами, формирование временной таблицы для фильтрации превращается в тяжелую операцию. Особенно это критично для файловых баз, где оптимизатор запросов работает менее гибко, чем в клиент-серверном варианте.
Самый эффективный способ решить проблему — внести исправления в текст запроса через расширение конфигурации или напрямую в модуле (если конфигурация снята с поддержки). Нам необходимо добавить условие ГДЕ Т.Ссылка = &УстановкаЦенНоменклатуры во вложенный запрос параметров виртуальной таблицы.
Посмотрим на пример исправленного и оптимизированного запроса, который работает за считанные секунды:
// В первой части пакета уже была помещена ТаблицаДанных с фильтром по ссылке
// Теперь используем её для получения среза последних цен
Запрос.Текст =
"ВЫБРАТЬ
| Товары.НомерСтроки,
| Товары.Номенклатура,
| ...
|ИЗ
| ТаблицаДанных КАК Товары
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаСреза,
| (Номенклатура, Характеристика, ВидЦены) В (
| ВЫБРАТЬ
| Т.Номенклатура,
| Т.Характеристика,
| Т.ВидЦены
| ИЗ
| ТаблицаДанных КАК Т // Используем уже отфильтрованную временную таблицу
| )
| ) КАК ЦеныНоменклатурыСрезПоследних
| ПО Товары.Номенклатура = ЦеныНоменклатурыСрезПоследних.Номенклатура
| И Товары.Характеристика = ЦеныНоменклатурыСрезПоследних.Характеристика
| И Товары.ВидЦены = ЦеныНоменклатурыСрезПоследних.ВидЦены";
Обратите внимание: мы заменили обращение к физической таблице Документ.УстановкаЦенНоменклатуры.Товары на обращение к временной таблице ТаблицаДанных, которая уже содержит только строки текущего документа. Это кардинально снижает объем обрабатываемых данных.
Фирма «1С» признала данную проблему и выпустила соответствующие исправления. Если вы не хотите править код вручную, проанализируем возможность автоматического исправления. Рекомендуется:
EF_00147985).Важно: После установки патча обязательно убедитесь, что в базе нет старых расширений, которые могли бы перекрывать модуль печати и мешать работе исправления.
Если после исправления запроса печатная форма все равно «подтормаживает», разберем сопутствующие причины, которые могут замедлять процесс в 1С v8.3:
ЦеныНоменклатуры. Если итоги не рассчитаны или установлены на очень старую дату, выполнение виртуальных таблиц типа СрезПоследних будет происходить крайне медленно. Воспользуйтесь обработкой Управление итогами.Полными правами. Если под админом все быстро — проблема в настройках и индексации полей, используемых в RLS.Тестирование и исправление с отмеченным пунктом Реиндексация таблиц информационной базы.Подводя итог, проанализируем последовательность действий для быстрого решения задачи:
СформироватьПечатнуюФормуУстановкиЦенНоменклатуры.ГДЕ Т.Ссылка = &УстановкаЦенНоменклатуры во вложенном запросе к табличной части.EF_....1Cv8.1CD утилитой chdbfl.exe.Соблюдение этих рекомендаций позволит сократить время формирования печатной формы с нескольких минут до 1–2 секунд, обеспечив комфортную работу пользователей в программе 1С:Управление торговлей 11.5.