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