Дерево значений в «1С»: где заканчивается удобство и начинаются «тормоза»
Разработка - Механизмы платформы 1С
О решении этой задачи рассказывает Ирина, разработчик 1С в нашей команде
ДеревоЗначений — один из самых коварных объектов. Оно идеально для визуализации иерархии, но при неправильном подходе превращает интерфейс в «тыкву». Главная проблема — сериализация: при каждом серверном вызове дерево гоняется целиком. Если в нем 100 000 строк, интерфейс «умрет». Разберем, как заставить его летать.
1. Ленивая загрузка (Lazy Loading) — Технически верно
Чтобы дерево открывалось мгновенно, подгружайте данные только при развертывании узла.
Шаг 1: Создаем маркер-пустышку (Сервер)
Если у узла есть дети, нужно «обмануть» платформу, чтобы она отрисовала «плюсик». Для этого добавляем одну пустую строку.
bsl
// На сервере при заполнении уровня (инициализация корня)
НоваяСтрока = КоллекцияВерхнегоУровня.Добавить();
НоваяСтрока.Наименование = "Группа товаров";
Если Выборка.ЭтоГруппа Тогда
// ПРАВИЛЬНО: Добавляем пустую подчиненную строку-маркер.
// Платформа увидит Количество() > 0 и нарисует "+" у узла.
НоваяСтрока.ПолучитьЭлементы().Добавить();
КонецЕсли;
Шаг 2: Обработка события (Клиент)
Используем штатное событие таблицы ПередРазворачиванием(Элемент, Строка, Отказ). Параметр Строка здесь — это идентификатор (Число).
bsl
&НаКлиенте
Процедура ДеревоПередРазворачиванием(Элемент, Строка, Отказ)
Узел = ДеревоДанных.НайтиПоИдентификатору(Строка);
Дочерние = Узел.ПолучитьЭлементы();
// ПРОВЕРКА: Если там только наша "пустышка" (одна строка без данных)
Если Дочерние.Количество() = 1 И Дочерние.Ссылка.Пустая() Тогда
ПодгрузитьДанныеНаСервере(Строка);
КонецЕсли;
КонецПроцедуры
Шаг 3: Дозагрузка данных (Сервер)
bsl
&НаСервере
Процедура ПодгрузитьДанныеНаСервере(ИдентификаторСтроки)
РодительскийУзел = ДеревоДанных.НайтиПоИдентификатору(ИдентификаторСтроки);
Коллекция = РодительскийУзел.ПолучитьЭлементы();
Коллекция.Очистить(); // Удаляем маркер-пустышку
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, Наименование, ЭтоГруппа ИЗ Справочник.Номенклатура ГДЕ Родитель = &Родитель");
Запрос.УстановитьПараметр("Родитель", РодительскийУзел.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = Коллекция.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
Если Выборка.ЭтоГруппа Тогда // Снова ставим маркер для следующего уровня
НоваяСтрока.ПолучитьЭлементы().Добавить();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
2. Рекурсия vs Итеративный обход (Стек)
Рекурсия — это красиво, но медленно и опасно (Stack Overflow). 1С тратит ресурсы на каждый вызов процедуры и управление стеком.
КАК НЕ НАДО, Если Деревозначений имеет большой объем(Рекурсия):
bsl
Процедура Обход(Строки)
Для Каждого Стр Из Строки Цикл
// Обработка...
Если Стр.Строки.Количество() > 0 Тогда // Лишний вызов метода в каждой итерации
Обход(Стр.Строки); // Рекурсивный вызов - ТОРМОЗИТ!
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Оптимальное (Итеративный обход через массив-стек):
Работает в 1.5–2 раза быстрее и никогда не упадет.
bsl
Процедура ОбходИтеративный(КорневыеСтроки)
Стек = Новый Массив;
Для Каждого Стр Из КорневыеСтроки Цикл Стек.Добавить(Стр); КонецЦикла;
Пока Стек.Количество() > 0 Цикл
ТекущаяСтрока = Стек[Стек.Количество() - 1];
Стек.Удалить(Стек.Количество() - 1);
// --- Полезная работа здесь ---
Подчиненные = ТекущаяСтрока.Строки;
Для Каждого Подч Из Подчиненные Цикл
Стек.Добавить(Подч);
КонецЦикла;
КонецЦикла;
КонецПроцедуры
3. Поиск: Забудьте про циклы
Метод НайтиСтроки(СтруктураОтбора, Истина) — это «черная магия» платформы на C++.
- Почему это оптимально: платформа обходит дерево напрямую в памяти, не создавая объекты «Строка» в интерпретаторе 1С.
- Когда НЕ использовать: если нужно искать 10 000 раз в цикле. В этом случае выгрузите дерево в ТаблицуЗначений, проиндексируйте её и ищите через ТЗ.Найти().
4. Оптимизация через СКД
Если дерево — это сложный отчет с итогами, не собирайте его запросами в цикле:
- Настройте СКД с иерархией группировок.
- Используйте ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений.
- СКД соберет дерево на уровне SQL и внутренних алгоритмов ядра, что в разы быстрее ручного заполнения.
Итоговый чек-лист производительности
|
Операция |
Ошибка (Тормоза) |
Решение (Скорость) |
|
Загрузка |
Всё дерево сразу |
Ленивая загрузка + "Пустышка" |
|
Обход |
Рекурсия |
Цикл Пока + Массив (Стек) |
|
Поиск |
Цикл Для Каждого |
НайтиСтроки(..., Истина) |
|
Оформление |
Сложные формулы И/ИЛИ |
Колонка-индекс цвета |
ДеревоЗначений — это визуальный объект, а не вычислительный. Считайте в таблицах или СКД, а пользователю отдавайте данные порциями через «Ленивую загрузку».
Вступайте в нашу телеграмм-группу Инфостарт
ДеревоЗначений Ленивая загрузка (Lazy Loading) Маркер-пустышка ПередРазворачиванием Итеративный обход (стек) Рекурсия НайтиСтроки СКД (СистемаКомпоновкиДанных) Сериализация
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
См. также
Механизмы платформы 1С Разработчик Бесплатно (free)
Разберем 15 мифов о работе платформы «1С:Предприятие 8» – как распространенных, так и малоизвестных. Начнем с классики: «Код, написанный в одну строку, работает быстрее, чем многострочный». Так ли это на самом деле?
16.07.2025 45725 TitanLuchs 109
Работа с интерфейсом WEB-интеграция Механизмы платформы 1С Бесплатно (free)
Веб-интерфейсы повышают качество внешнего вида приложений 1С, предсказуемы с точки зрения верстки, позволяют организовать удобные и высокопроизводительные рабочие места для пользователей. Расскажем об особенностях разработки веб-интерфейсов на React внутри 1С, двустороннем взаимодействии 1С и JavaScript, а также сборке веб-приложения в одностраничный файл.
19.06.2025 18727 zeegin 15
Механизмы платформы 1С Работа с интерфейсом Разработчик Стажер 1С:Предприятие 8 Бесплатно (free)
Про ООП в 1С и о том, как сделать свой код более кратким и выразительным при помощи использования текучего интерфейса (fluent interface).
03.02.2025 26067 bayselonarrend 127
Механизмы платформы 1С Разработчик 1С:Предприятие 8 Бесплатно (free)
В этой статье подробно рассматривается работа с JSON в XDTO в 1С:Предприятие. Вы узнаете, как сериализовать и десериализовать объекты XDTO в JSON, интегрировать 1С с веб-сервисами и API, а также корректно обрабатывать данные при обмене. Разбираются особенности работы с коллекциями, использование функций восстановления и частые ошибки при работе с JSON и XDTO.
30.01.2025 33359 user2122906 10
Механизмы платформы 1С Файловый обмен (TXT, XML, DBF), FTP Разработчик 1С:Предприятие 8 Бесплатно (free)
Этот материал познакомит вас с механизмом XDTO (XML Data Transfer Objects) в 1С и научит эффективно использовать его возможности. Мы разберёмся, как работать с XML-схемами, создавать модели данных, манипулировать объектами XDTO, а также сериализовать и десериализовать их в XML. Вы узнаете, как использовать XDTO для интеграции с внешними системами, избегать типичных ошибок и оптимизировать код. К концу вы будете уверенно применять XDTO для решения сложных задач обмена данными и автоматизации процессов.
17.01.2025 55912 user2122906 13
Механизмы платформы 1С WEB-интеграция Разработчик 1С:Предприятие 8 Бесплатно (free)
В платформе 8.3.27 появилась возможность использовать WebSocket-клиент. Давайте посмотрим, как это все устроено и чем оно нам полезно.
14.01.2025 46879 dsdred 110
Механизмы платформы 1С Разработчик 1С:Предприятие 8 Бесплатно (free)
Особенности "Знач" и разбор документации к нему.
10.01.2025 26495 VAAngelov 60
Механизмы платформы 1С Разработчик Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)
Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.
23.06.2024 40503 bayselonarrend 24
1) Ленивая загрузка - вы сами пишите, что дерево будет гоняться целиком между сервером и клиентом, но при разворачивании строки делаете серверный вызов. Разве не целиком дерево будет перерисовываться ?
2) Рекурсия - говорите, что Количество() - это лишний вызов метода в каждой итерации, но заменяете его на 2 метода Количество()
ЗЫ: Скучно вы на своем свечном заводике живете.
Этот классификатор составляет Федеральное казначейство.
Там тысячи строк.
На форме используется дерево, и данные подгружаются динамически, при развертывании, чтобы весь классификатор не тащить на клиент, и не замедлять открытие формы.
И вот на экране "дерево". Даже если оно динамически подгружается (это техническая нюансина), чьего внимания и памяти должно хватать, чтобы помнить что было "пять страниц назад". Я когда-то статью выкладывал "Искусство отчета". Я там именно такую ситуёвину и разбирал про гигантские визуализированные объекты, неважно - на экране или на бумаге. Человек не заточен под такой просмотр и анализ "на ходу", хотя есть феноменальные гении)
И сразу вопрос есть - каков функционал пользователя, который такое дерево выращивает на экране? В какой процедуре он работает? Какой конкретный документ обрабатывает?
Опять же, если человечек знает, в каком контексте он находится (пресловутые доходы бюджета), он заранее может этот контекст задать, типа "Доходы таможни". И тем самым резко произвести "весеннюю обрезку дерева", получив только нужную "веточку", которую так же можно (нужно!) уточнить по контексту.
Редко кому (хотя есть случаи, когда 1000 строк вполне приемлемо, особенно, если есть выделение ключевых позиций).
Так и статья именно про это, вы же не спрашиваете кому может понадобится поиск в индексе?
Имеем многоуровневое дерево, теоретически там может лежать 100 000 объектов.
Но нам нужно всего 5, поэтому человек и разворачивает только нужные узлы иерархии и вместо 100 000 строк реально видит 5-10 элементов.
Все равно вы где-то правы, плохо дерево приспособлено для фокусов, см. п.2. ниже.
Мне неясны 3 момента:
1. Почему не предусмотрена очистка заполненных узлов по мере их закрытия (лучше не в лоб, а через свой "сборщик мусора")?
2. Что произойдет, если надо будет что-то искать не путем интерактивного разворачивания строк.
Может получиться оригинально - все быстро, пока щелкаем мышкой по узлам, а решили что-то найти, задав, например, артикул и приехали - либо заполнять дерево полностью и искать стандартно, либо делать запрос к базе, искать где это у дерева может лежать, заполнять все нужные узлы и листья и потом уже показать результат.
Как вариант - для такого поиска показывать отдельное дерево? :)
3. Кажется неразумным при каждом разворачивании "пустого" узла делать запрос к базе.
Разумнее продумать предвыборку по путям наиболее вероятного обхода.
Так сказать "спекулятивно исполнять инструкции, предотвращая простои конвейера".
Вообще, стоит продумать алгоритм первоначального заполнения дерева - вполне вероятно, что верхние уровни иерархии разумней заполнять сразу.
ЗЫ: вот, например, бухня с битом и чем-то там своим сверху. 4к общих модулей, 1,3к справочников, 800 документов, ...........
1С однажды должна для себя определить, что "мы создаём ПО отнюдь не только для малого бизнеса" (как это у них исторически сложилось). А пока пытаются надстроить хоромы на том фундаменте, который однажды основали под хижину дяди Тома)
Дерево как раз про это. Реально так и получается при хорошей балансировке, разумеется.
Что касается людей - функций, то истина где-то посередине. Человек "от-до", работает только, если вы смогли превратить его в винтик и контролируете, что он работает при НУ (нормальных условиях) иначе беда для всех.
Мне хватил общения с "поддержкой" МТС - попадаются заводные обязьянки с IQ 40. Они как раз делают строго, что велено, результат - удручающий.
(11)
Нас этим не запугать :)/
Я каждый день работаю с деревом конфигурации УПП, допиливаемой с лохматых годов.
И кол-во объектов, не самый не приятный момент. Еще ведь творчески можно подойти к их наименованию и, вообще, использованию.
ЗЫ: да, я все вру. Интернеты пишут, что 50 и ниже - это умственная отсталость, а 70 - нижний уровень слабого интеллекта. Дробышевский говорит другое, например про IQ тупайи, что он 50. Даже не знаю, кто тут прав )))
Поиск в индексе тем и хорош, что пользун уже знает - что он ищет, он не собирается бегать глазами по тысяче и даже по сотне строк, десяток-полтора максимум!
По пункту 2. Я не случайно спросил про функционал пользователя. Этой науке меня когда-то научил очень квалифицированный мастер (из Министерства общего машиностроения СССР). Если у сотрудника какая-то часть рабочей нагрузки строится по принципу "вдруг понадобится", то это повод для серьёзных организационных выводов. На предприятии работают люди-функции. А люди "вдруг понадобится" работают в НИИ, где вечно что-то пробуют. Нерационально писать какой-то код под функционал в стиле "если надо будет". Сидит человек с конкретной должностью и должностными (функциональными) обязанностями и ему - "вдруг") Как говаривал главный герой "Белого солнца пустыни": "Эт, вряд ли!"))
Пункт 3. Продолжение пункта 2. На каждом рабочем месте УЖЕ ЗАРАНЕЕ известно что и кому "надобится". Не дай Кришна расплодить у себя в офисе кучу творческих личностей, вечно находящихся в каком-то поиске) Сегодня то хотят "посмотреть", завтра - "другое"... Это бывает, когда сотрудник работает не от функционала, а от "режима прерывания", в стиле что мне "позвонят", то я и делаю. А если никто не позвонит, то я сам и не знаю - что мне делать. В современных офисах таких сотрудников -"телефонистов" с избытком.
Увы, но сейчас проектирование ИТ до неприличия мало содержит мер административно-организационного характера, которые всегда идут впереди кодирования. Именно это и избавляло от красивого, но избыточного кодирования.
Есть техническая возможность - получить с сервера, слепить иерархию, сделать много красивых премудростей для фильтраций и т.д. Такие возможности и аппаратные мощности конечно есть, и написать можно очень красиво, не спорю.
А есть организационная мера - обследовать рабочее место сотрудника, его функционал, какова его роль в общих процессах, как-то систематизировать обрабатываемую информацию и т.д. Вообщем, то, что когда-то относительно неплохо умели делать, чтобы сотрудники не "сёрфили" по информации, как привыкли делать это в интернете, а занимались чем-то конкретным)
Я сторонник организационных мер, в первую очередь. Они дешевле, понятнее и дают гораздо более быстрый и долгосрочный эффект.
У меня есть примерное объяснение. Это родилось исключительно на почве моих мироощущений и личных оценочных суждений, тем не менее...
У нас есть некая псевдосекта "Свидетели бигдаты". Ну есть группа товарищей, которая на форумах, в чатах, на всяких сейшенах и митапах, да и просто в общении с коллегами любят подкатить глаза и с акцентированным вздохом произнести "Да у меня в базе уже стопиццот терабайт..." И глазёнками так зырк-зырк по сторонам - не упал ли кто от такой ошеломляющей цифры. При том, что нет никакого анализа - насколько оправдана такая "ИТ-опухоль" на трещащих и стонущих серверах. Ну хочется чем-то в бане помериться) Эти персонажи любят всё большое, объёмное - автомобили, женщин и визуальные объекты в интерфейсах. И тащатся от построения неких аналогов "Бурдж Калифа", только в виртуале. Нет в этом хорошей логики и объективной потребности. Построение любого просмотра, особенно, из объёмного источника, предполагает изначальное наложение границ отборов, при том, что эти границы обеспечат реально просматриваемое и анализируемое количество информации. А для обычного человечка это вполне мизерный объем информации, примерно на пол-экрана небольшого монитора. Кто-то высокого мнения о своих когнитивных возможностях? Вперёд! В Инете дофигищи всяких тестов, только не ставьте сразу высокий уровень проверки - разочарование может больно ранить самолюбие)
То, что где-то есть интерфейсы с гигантскими "секвойями" в интерфейсе, ничуть не говорит о разумности и удачности такого решения. Больше похоже на рекламный ход, типа "Посмотрите, как у нас для вас всего дофига!".
Поставить на стол компьютер и пользоваться им в режиме "листания"? Серьёзно?? А зачем тогда складскую книгу перестали вести и картотеку выкинули. Там листать интереснее - есть тактильные ощущения)
Какой размер у создаваемого дерева вообще есть. В абсолюте, будет построен бао-баб, размером во всю базу, с последующим окорением, срезанием вершинок и сучков. В чем логика? А что, из самой базы сразу нельзя получить квантик информации, размером с экран монитора? Вы понимаете, что термин "посмотреть" автоматически проваливает пользователя в абсолютно ручной режим работы. То есть, представим ситуацию, что я, как работодатель, вложился в рабочее место сотрудника с компьютером, заплатил программистам за автоматизацию, чтобы - что? Чтобы зависеть от глазынек сотрудника и уповать, что он-таки не проморгает одну строчку из тысячи (многих тысяч??)? И каковы шансы на такой успех? "Извини, босс, я не увидел - глаза на лоб уже вылезли....". Спасибо, автоматизаторы)
В этой связи простой вопрос, кто-то читал ГОСТ по разработке ПО (текущий или предыдущий, не суть)? Цели и задачи автоматизации именно так сформулированы - сымитировать ручной режим работы, но будет чуть быстрее, так?
- Сосед! Почему у тебя свинья на протезах??
- А мне что, ради одного холодца всю свинью забивать?!
Вот идеальный подход в любой автоматизации) Очень быстро получать небольшие порции информации, необходимой именно в текущем процессе. Разного рода информация, "мне чисто посмотреть" - это крах автоматизации. Посмотреть - это в Дискавери...
Работает в 1.5–2 раза быстрее и никогда не упадет.
&НаКлиентеНаСервереБезКонтекста
Процедура ОбойтиДеревоЦикломОптимизация(Строки)
Стек = Новый Массив;
Для Каждого Стр Из Строки Цикл Стек.Добавить(Стр) КонецЦикла;
Индекс = 0;
Пока Индекс < Стек.Количество() Цикл
Стр = Стек[Индекс];
Индекс = Индекс + 1;
// полезная работа
Для Каждого Подч Из Стр.ПолучитьЭлементы() Цикл Стек.Добавить(Подч) КонецЦикла;
КонецЦикла;
КонецПроцедуры ПоказатьЗаполнение дерева можно делать в фоне и получать готовое при разворачивании веток.
(19) Деревья метаданных используются в различных инструментах типа консолей запросов. Так что замеры нужны и с отладчиком и без.
подвергаю сомнению статьей из ИТС (
&НаКлиенте
Процедура ДеревоПередРазворачиванием(Элемент, Строка, Отказ)
Узел = ДеревоДанных.НайтиПоИдентификатору(Строка);
Дочерние = Узел.ПолучитьЭлементы();
// ПРОВЕРКА: Если там только наша "пустышка" (одна строка без данных)
Если Дочерние.Количество() = 1 И Дочерние.Ссылка.Пустая() Тогда
ПодгрузитьДанныеНаСервере(Строка);
КонецЕсли;
КонецПроцедуры
ПоказатьКонкретно
Если Дочерние.Количество() = 1 И Дочерние.Ссылка.Пустая() ТогдаА именно у коллекции Дочерние берём поле Ссылка и проверяем его на "пустотность". Но ведь у Коллекции этого поля же нет? не так ли?
Может надо так?
Если Дочерние.Количество() = 1 И Дочерние[0].Ссылка.Пустая() ТогдаРейтинг: 2152
Вы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 2629585
Создание 02.03.26 16:00
Обновление 02.03.26 16:00
Просмотры 3611
Загрузки 0
Рейтинг
25
Комментарии 45
Код открыт Да
Рубрики Механизмы платформы 1С
Кому
Разработчик
,
Стажер
Тип файла Нет файла
Платформа 1С 8.3
Конфигурация Универсальные
Операционная система Не имеет значения
Страна Не имеет значения
Отрасль Не имеет значения
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Бесплатно (free)