Данные формы и оптимизация обмена с сервером

29.09.14

База данных - HighLoad оптимизация

Почему может сильно тормозить форма, где есть "ДанныеФормыКоллекция", "ДанныеФормыДерево" и им подобные, и как этого избежать.

"ДанныеФормы..." Синтакс-помощник не балует нас избыточной информацией, сообщая лишь, что объект этого рода, в общем случае, "предназначен для моделирования коллекций в данных управляемой формы" и "может использоваться в реквизитах управляемой формы". Для "ДанныеФормыКоллекция", по идее, моделируется таблица значений, для "ДанныеФормыДерево" - дерево значений, и так далее. Общеизвестно, на ИТС и в статьях разжёвано, что эти объекты живут на клиенте с целью адекватно отобразить, в т.ч. в связке с элементами УФ, те или иные данные; а также, что они доступны и на сервере как минимум при передаче всего контекста формы. Моделировать можно коллекции прикладных объектов из БД, а можно и свои, временные, созданные прямо в форме для служебных и рабочих надобностей. Вот о них и пойдёт речь - о моделях коллекций, являющихся реквизитами управляемой формы и отражающих некие не единичные объёмы данных.

Поскольку поведение этих моделей отличается в разных версиях платформы, возьмём 8.2.19.106 и 8.3.5.1119; для чистоты эксперимента создадим для каждой версии совсем пустую конфигурацию и будем гонять в режиме тонкого клиента, безо всяких совместимостей, замеряя производительность с помощью штатных средств платформы.

Сделаем внешнюю обработку, в ней форму, и для этой формы создадим два реквизита - с типом "Таблица значений" и с типом "Дерево значений" (разумеется, они покажутся в скобках как несуществующие на клиенте). Создадим по 4 реквизита-колонки к каждому из этих, дадим им типы - строковый (250), число (15.2), дата (дата-и-время), булево. Желающие могут поэкспериментировать со ставшими возможными в 8.3 "произвольными", а также с вложением всяких других моделей коллекций типа "матрёшка", но мы будем работать с этими простыми данными, чья возможность сериализации штатным образом очевидна. На интерфейсе, в элементах формы, ничего делать не станем.

Заполним таблицу значений - сначала по 1000 строк, потом будем пробовать больше. Дерево значений, а точнее, моделирующая его коллекция, понадобится как "гиря", сразу дающая разницу в объёмах данных на порядки. Строковую колонку везде забьём мусором под все 250 символов.

Итак, что нам интересно? Допустим, мы делаем внешнюю универсальную обработку, в чьих реквизитах формы никак не задействованы сущности БД, но по ряду причин очень нужно использовать большие модели коллекций. Например, это обзор файлов на клиентском ПК - дерево каталогов и некая таблица значений нужных юзверю файлов. Главное, что нам совершенно незачем обрабатывать все данные на сервере, мы добровольно отказались от индексации таблицы значений и вообще хотим в первую очередь оптимизировать передачу данных между клиентом и сервером. Подчеркну - дерево большое, таблица значений сравнительно маленькая.

Исходная задача - всего лишь по каким-то нашим нуждам поработать с таблицей значений, "вынимаемой" из её модели. Да, можно возразить, что мол "чего тебе не хватает" - и сортировка есть, и поиск, и обход колонок можно смоделировать - но вот допустим, для эксперимента. Я, может, хочу СКД-образную выборку запилить по таблице, с ветками "И"-"ИЛИ", по заданной юзверем логике.

Вроде бы это просто - вызвать контекстную серверную процедуру и там выполнить "ДанныеФормыВЗначение", вуаля. Но здесь и начинаются подводные камни, потому как вместе с безусловно нужной нам моделью таблицы значений на сервер в рамках контекста тащится и огроменная "ДанныеФормыДерево", которая вообще там не нужна.

К сожалению, разработчики платформы не дали нам возможности избирательно управлять передачей контекста формы между клиентом и сервером. Флаг "Использовать всегда" для реквизитов этих моделей вообще не играет роли, а другого и нет, и в результате вызов сервера превращается в тормоза и недопустимо высокий объём отправляемых данных.

Очевидно, что вызов должен быть внеконтекстным. Но тогда коллекции недоступны, и их надо как-то в целевую серверную процедуру передать. Тут начинается разница - в 8.2 можно передать "ДанныеФормы" как аргумент на сервер, их передача происходит без ошибок и без потерь, но на ИТС читаем, что это очень некомильфо, что в принципе логично, т.к. кто его знает, как оно там размещается, где в памяти болтается, куда на сервере приложений девается и как себя поведёт при изменении без указания "Знач".

Всякие "ХранилищеОбщихНастроек.Сохранить" или "ЗначениеВСтрокуВнутр" неприменимы на клиенте и отпадают.

Казалось бы, используем "ПоместитьВоВременноеХранилище" (естественно, с соблюдением и пониманием, какие ключи нужны и сколько времени оно проживёт - ну, нам на один вызов, и хватит). Тем более, что в СП никаких ограничений на этот счёт не указано, а значит, находясь в форме, вполне можно поработать с временным хранилищем. И в 8.2 это удаётся без проблем, и мы получаем вожделенный результат. Сделали внеконтекстно вызываемую процедуру, на клиенте помещаем модель-коллекцию в хранилище, передаём адрес как аргумент этой процедуре, а в ней, на сервере, получаем из хранилища. Все счастливы, всё работает, объём данных минимален благодаря тому, что мы сами решаем, какие объекты помещать и передавать - т.е. только и исключительно нужную нам таблицу, а никакое не дерево.

Но в 8.3 нас ждёт неприятный сюрприз: 8.3.4 просто заявляет, что подобные объекты "не могут быть помещены в хранилище", а 8.3.5 громко падает с ошибкой. Скромно осмелюсь полагать, что это просто временная недоработка писателей платформы, ибо если данные можно было передавать в 8.2, то что мешает повторить достигнутое? Поэтому надеюсь, что примерно к 8.3.10 это аккуратно доделают, а не оставят как сейчас и не объявят "фичей", подогнав заумное обоснование.

Что делать? А делать сериализацию своими силами. Это даже лучше, всё под нашим контролем. Приведу кусок кода с контекстным и внеконтекстным вызовами, которые дали мне статистику.

&НаСервереБезКонтекста
Процедура Сгонять_СерверБезКонтекста(стро)
   
рЧтениеХМЛ=Новый ЧтениеXML;
   
рЧтениеХМЛ.УстановитьСтроку(стро);
   
рТаблицаЗначенийС=СериализаторXDTO.ПрочитатьXML(рЧтениеХМЛ);
   
Сообщить("К-во табзнач: "+рТаблицаЗначенийС.Количество());
КонецПроцедуры

&НаКлиенте
Процедура СгонятьБезКонтекста(Команда)
   
рЗаписьХМЛ=Новый ЗаписьXML;
   
рЗаписьХМЛ.УстановитьСтроку();
   
СериализаторXDTO.ЗаписатьXML(рЗаписьХМЛ,рТаблицаЗначений);
   
Сгонять_СерверБезКонтекста(рЗаписьХМЛ.Закрыть());
КонецПроцедуры


&НаСервере
Процедура Сгонять_Сервер()
   
Сообщить("К-во табзнач: "+рТаблицаЗначений.Количество());
КонецПроцедуры

&НаКлиенте
Процедура Сгонять(Команда)
   
Сгонять_Сервер();
КонецПроцедуры


В результате получаем адекватную передачу "ДанныеФормыКоллекция" на сервер, и опять же, избирательно, что экономит нам объёмы и время. Причём это именно полноценный объект, с которым вполне можно работать, хотя мы даже не указали сериализатору тип значения, читаемого из xml, он сам догадался.

Поставив ряд экспериментов, можно убедиться, что при прочих равных передача контекста всей формы это не худший, а порой и оптимальный вариант, но только если а) в ней нет чего-то тяжёлого и/или б) всё или почти всё реально нужно на сервере. В случаях же, когда на форме преизрядно разных данных, и среди них объёмистые модели коллекций, проще использовать сериализацию только нужных данных и их передачу во внеконтекстные серверные процедуры. В таблице на приложенном рисунке приведены результаты экспериментов - вызовов вышеуказанного кода - и краткие пояснения. Извиняюсь, что не включаю таблицу в текст статьи - но html-редактора ИС в очередной раз не превозмог (((

Зелёным цветом показаны успешные варианты, когда мы сэкономили, а красным - когда наоборот)

Заметим, что объём передаваемых данных в нашем случае порождён обычной строкой, куда свернулся xml, а значит, её тоже можно чем-нибудь "ужать", и вопрос, как всегда, во времязатратах относительно выигрыша по размеру.

Также заметим, что в 8.2 объём принятых данных не меняется, тогда как в 8.3 при нашем способе принимается столько же, сколько передавалось. Не берусь объяснить сей эффект - надо больше знать о "глубинах".

Однозначного рецепта нет, решать приходится по ситуации, но способ максимально облегчить обмен, поработать на сервере только с нужными моделями коллекций, и взятыми из них реальными коллекциями, у нас есть. Успеха!


Клиент-сервер сериализация ДанныеФормыКоллекция ДанныеФормыДерево

См. также

Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы

HighLoad оптимизация Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    2430    spyke    26    

39

Анализируем SQL сервер глазами 1С-ника

HighLoad оптимизация Инструменты администратора БД Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Обработка для простого и удобного анализа настроек, нагрузки и проблем с SQL сервером с упором на использование оного для 1С. Анализ текущих зааросов на sql, ожиданий, конвертация запроса в 1с и рекомендации где может тормозить

1 стартмани

15.02.2024    7361    149    ZAOSTG    66    

95

Удаление строк из таблицы значений различными способами с замером производительности

HighLoad оптимизация Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Встал вопрос: как быстро удалить строки из ТЗ? Рассмотрел пять вариантов реализации этой задачи. Сравнил их друг с другом на разных объёмах данных с разным процентом удаляемых строк. Также сравнил с выгрузкой с отбором по структуре.

09.01.2024    5769    doom2good    48    

63

Опыт оптимизации 1С на PostgreSQL

HighLoad оптимизация Бесплатно (free)

При переводе типовой конфигурации 1C ERP/УТ/КА на PostgreSQL придется вложить ресурсы в доработку и оптимизацию запросов. Расскажем, на что обратить внимание при потерях производительности и какие инструменты/подходы помогут расследовать проблемы после перехода.

20.11.2023    8595    ivanov660    6    

75

ТОП проблем/задач у владельцев КОРП лицензий 1С на основе опыта РКЛ

HighLoad оптимизация Бесплатно (free)

Казалось бы, КОРП-системы должны быть устойчивы, быстры и надёжны. Но, работая в рамках РКЛ, мы видим немного другую картину. Об основных болевых точках КОРП-систем и подходах к их решению пойдет речь в статье.

15.11.2023    4999    a.doroshkevich    20    

72

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    15965    skovpin_sa    14    

98

Как эффективно настроить autovacuum в Postgres для 1С

HighLoad оптимизация Администрирование СУБД Платформа 1С v8.3 Бесплатно (free)

Кто не любит убирать мусор? Думаю, практически все, а вот в Postgres это обязательный ритуал для эффективной работы. Как эффективно настроить уборку за 1С в Postgres, можно прочитать в этой статье и еще раз задуматься о бесплатности Postgres.

05.08.2023    4976    1CUnlimited    5    

51
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Yashazz 4707 29.09.14 22:43 Сейчас в теме
Да, и понятное дело, что мы на сервер кидаем копию, "слепок" с данных формы, а они сами тихо лежат на клиенте, и если их надо изменить-обработать, то с сервера потом придётся тащщить обратно той же сериализацией и на клиенте обновлять, например, через КопироватьДанныеФормы(Десериализованное,СвоёМестное).

Если я написал баян, просьба кинуть тапком, т.е. ссылкой. Самому слабо верится, что эти моменты ранее не разбирали.
2. BabySG 01.10.14 19:22 Сейчас в теме
(0)
Но в 8.3 нас ждёт неприятный сюрприз: 8.3.4 просто заявляет, что подобные объекты "не могут быть помещены в хранилище", а 8.3.5 громко падает с ошибкой. Скромно осмелюсь полагать, что это просто временная недоработка писателей платформы, ибо если данные можно было передавать в 8.2, то что мешает повторить достигнутое? Поэтому надеюсь, что примерно к 8.3.10 это аккуратно доделают, а не оставят как сейчас и не объявят "фичей", подогнав заумное обоснование.

Смысл в том, что в 8.2 ОШИБОЧНО разрешалось запихивать подобные данные в хранилище. В 8.2 (ранних версиях) туда можно было еще и COM объект запихнуть.
А дальше удивлялись - а куда он делся и почему COM не работает :)
Еще есть вариация, когда возвращалось НЕОПРЕДЕЛЕНО (Кстати, разработчики типовых тоже наступили на эти грабли)
А еще есть ответ от разработчиков, который датируется 2011 годом. Но, как я помню. Вы не участвуете тут https://partners.v8.1c.ru/forum/message/886492#m_886492, поэтому цитата:
Во временном хранилище могут хранится значения помеченные в синтакс помощнике как "Сериализуется".

Что, кстати, также описаное в СП для метода ПоместитьВоВременноеХранилище
Описание:
Сохраняет сериализуемое значение во временное хранилище.
3. Yashazz 4707 01.10.14 19:58 Сейчас в теме
(2) ОК, была мысль и что "ошибочно разрешили", недопилив концепт, согласен; но почему штатный сериализатор легко справляется без потерь и проблем? Почему нельзя было это же сделать для временного хранилища?

И кстати, какой криминал в сериализации некоей модели данных, коей являются ДанныеФормы, если там в её реквизитах не болтается ничего предосудительного, а всё сплошь простые типы или ссылки? Неужели это так преступно и жутко?
4. BabySG 02.10.14 08:24 Сейчас в теме
(3) Смысл в том, что данные не "сериализируются" в этом случае, а именно модифицируются.
Отдаленно можно сравнить с тем, что СправочникОбъект нельзя передать на сервер с клиента (и наоборот), хотя платформа сама-то как-то "понимает", что делать при записи из формы.
PS. Тут еще такой момент: данные сеанса (а именно в них хранится временное хранилище) могут мигрировать между сервера кластера, и совершенно не факт, что поднятые данные формы будут иметь отношения к какой-либо форме - ее может не быть на другом сервере (например, форма пересоздалась после падения процесса на сервере). Эта же прчина мешает запихать в ВХ COM объект - что делать, если на сервере нет контекста подключения или вообще попали на сервер с Linux?

PPS. А сама задача предварительной обработки большого массива данных через данные формы - крайне не рекомендуется разработчиками платформы. Крайне негативно влияет на оптимизацию передачи данных (что и видно из статьи). Рекомендуют делать небольшую подготовку и отправлять на сервер для полной обработки. Конечно, не всегда есть возможность отпраить туду все, поэтому приходится в каждом случае придумывать свое решение. Универсального нет (вот у нас есть алгоритм, кторый работает по трем веткам, все зависит от объема данных)
5. Yashazz 4707 02.10.14 10:28 Сейчас в теме
(4) По идее - целиком согласен. Я ведь и в комментарии приписал, что хочу манипулировать со слепком, с мёртвой копией, которая вообще уже оторвана от формы, контекста, исходника, и никакой логической связи ни с чем не держит. Просто некая коллекция. Если мне понадобится "обратная связь", буду сам прыгать, по каким-то идентификаторам совмещать.
И хранилище тут можно лепить привязанное куда угодно, согласен.
Насчёт COM - тоже абсолютно согласен, очевидные вещи.

Дык в том и фишка, что я хочу кидать небольшой объём и не тащить контекст. Согласитесь, могут, ещё как могут быть огромные данные, чисто по логике бизнес-задачи, пришедшие с клиента. Тот же COM, или ещё что, и не всегда можно выкрутиться.

Кстати, до кучи: почему у обычного "ДеревоЗначений" нету метода "Скопировать", не знаете случайно? Только передача по ссылке и фиг сделаешь независимую копию, кроме как построчно...
6. BabySG 02.10.14 11:33 Сейчас в теме
(5) В том случае, если нужно что-то передать с клиента на сервер (например, тот же файл) - то, как раз, его и передаем через хранилище.
Как вариант, мы можем его обработать на клиенте и создать из оригинального новый уменьшеный и его уже передать на сервер. В этом случае данные формы мы не трогаем, гоняем только то, что сами выбрали.
Но нужно понимать - в каждом конкретном случае, для каждой задачи: свое решение. Тут не получится сделать универсально (данные формы, по сути, и есть универсально, но не будет работать на больших объемах)
7. Yashazz 4707 02.10.14 13:02 Сейчас в теме
(6) Именно. И задача иногда бывает именно требующая решения тех проблем, о которых я пишу. Например, не можем сразу забросить файл - юзверь хочет сначала посмотреть его содержимое в виде красиво оформленного интерфейса, отметить флажками нужное к обработке, и уж тогда айда на сервер. И бывает, что некоторые операции с клиентскими ипостасями этих интерфейсных объектов требуют втихую некоторым объёмом поработать на сервере.
8. dj_serega 390 02.10.14 15:15 Сейчас в теме
А если протестить две ТЗ и два ДЗ где будет выигрыш?
9. Yashazz 4707 02.10.14 15:18 Сейчас в теме
(8) Смотря какого они размера. Тут фишка не столько в типе объекта, сколько в его наполнении. Но по моим ощущениям древовидные объекты сериализуются медленнее. В моём примере дерево просто служило эталонной тяжестью, могло ведь быть и строго наоборот - крохотное деревцо и огромная таблица значений.
10. dj_serega 390 02.10.14 15:39 Сейчас в теме
(9) если я правильно понял то:
есть 2 ТЗ + 2 ДЗ (по 1000) то один из объектов лучше контекстом обрабатывать?
11. Yashazz 4707 02.10.14 16:48 Сейчас в теме
(10) Если надо обработать 1 из 4 - лучше внеконтекстно. Если 3 из 4 или все - лучше контекстно. Нет однозначного рецепта, всё зависит от наполнения - может, там в ячейках нескольких строк прячутся свои монстры - всякие подтаблицы да массивы, да структуры, да ещё картинки...
12. bonv 1508 02.10.14 18:08 Сейчас в теме
&НаКлиенте
Процедура СгонятьБезКонтекста(Команда)
    рЗаписьХМЛ=Новый ЗаписьXML;


В веб-клиенте это не будет работать.
13. Yashazz 4707 02.10.14 18:29 Сейчас в теме
(12) Да. Есть такая печаль. Там останется только моделировать это всякими костылями вроде массивов структур и прочая.
14. PiccaHut001 07.10.14 18:39 Сейчас в теме
(0) "Поэтому надеюсь, что примерно к 8.3.10 это аккуратно доделают, а не оставят как сейчас и не объявят "фичей", подогнав заумное обоснование." - зря надеетесь, 1с так делают ВСЕГДА
Оставьте свое сообщение