Пятница, 03.05.2024, 00:24
Приветствую Вас Гость | RSS
Главная Каталог статей Регистрация Вход
Меню сайта

Категории каталога
Алгоритмические трюки [1]
В этой категории собраны статьи по интересным или нестандартным алгоритмическим решениям различных прикладных ситуаций.

Главная » Статьи » Алгоритмические трюки

Повышение производительности при выборке по иерархии
Повышение производительности при выборке по иерархии

Структура хранения иерархических объектов 1С:Предприятия довольно проста. Каждая запись в таблице такого объекта имеет служебное поле, в котором хранится ссылка на родительский элемент. Это удобно для отображения списка справочника, когда отображаются элементы текущей (открытой в данный момент) группы. Однако выборка по иерархии подразумевает рекурсию выборок.

Когда в запросе используется конструкция «ГДЕ ХХХ.Ссылка В ИЕРАРХИИ (&YYY)», платформа сначала формирует список таких элементов по алгоритму:
1) создать пустой список элементов к последующей обработке;
2) добавить в него Параметр, переданный в запрос и установить на него указатель списка;
3) выбрать элементы, где Родитель=&(значение в указателе списка) и ЭтоГруппа;
4) добавить выбранные элементы в конец списка к последующей обработке;
5) сдвинуть указатель на следующую позицию;
6) если удалось (не достигнут конец списка), перейти к (3).
Полученный список и используется как параметр запроса, а конструкция «ГДЕ ХХХ.Ссылка В ИЕРАРХИИ (&
YYY)» заменяется на «ГДЕ ХХХ.Родитель В (&Список)»

Механизм довольно понятный и простой, однако малоэффективный. При достаточно большом ветвлении дерева данный подготовительный процесс занимает продолжительное время.

Например: в компаниях, торгующих запасными частями к автомобилям, каталоги товаров имеют достаточно большое ветвление по производителям, по узлам и агрегатам, и т.д. Для справочника «Номенклатура», в котором 80 000 элементов из которых 800 - группы, такой процесс может занимать до 3 секунд на нормальном, современном сервере. Но и основной запрос, в котором используется конструкция «В (&Список)» требует перебора всех записей таблицы и не оптимизируется сервером баз данных.

Введя небольшое функциональное ограничение, можно в корне изменить ситуацию. Основная цель состоит в том, чтобы одним запросом выбирать все ниже лежащие элементы. Для этого нужно ввести составной ключ, который будет содержать сумму кодов всех выше стоящих элементов. Пример: элемент имеет код 156 и находится на 3-м уровне справочника, код его родителя 112, код родителя его родителя 89 – в поле ключ должно быть записано «089112156». В таком случае все элементы, принадлежащие группе с кодом 89, будут иметь «089*» в ключевом поле. Элементы, принадлежащие группе с кодом 112, будут иметь «089112*» в ключевом поле. Этот подход позволяет заменить условие запроса «ГДЕ ХХХ.Ссылка В ИЕРАРХИИ (&ВыбГруппа)» на «ГДЕ ХХХ._Код ПОДОБНО "ВыбГруппа._Код%"» или «ПОДСТРОКА (ХХХ._Код, 0, " + СтрДлина(ВыбГруппа._Код) + ") = &ВыбГруппа._Код» для выбора всех элементов, принадлежащих группе «ВыбГруппа».

Рассмотрим реализацию данного подхода. Если мы предположим, что в одной группе не может находиться более N элементов, тогда для уникального определения элемента внутри группы достаточно Цел(Log10(N))+1 десятичных разрядов. Для общности мы будем полагать N=99999 (что редко достижимо на практике), в этом случае число необходимых разрядов 5. Теперь добавим в таблицу дополнительный индексируемый реквизит, например «_Код», строкового типа с длиной, достаточной для хранения нашей глубины иерархии. Если ожидается максимально 10 вложенностей, длина поля должна быть (10+1)*5=55. В модуле объекта справочника создадим процедуру ПередЗаписью, в которой сформируем новое значение ключа: _Код=СокрЛП(Родитель._Код)+Формат(Код,"ЧЦ="+РазрядностьКода+"; ЧВН=; ЧГ=0"). В форматной строке мы указываем, что нужно выводить лидирующие нули, дополнять длину строки нулями до разрядности кода и отключаем поразрядную группировку. Особое внимание нужно уделить изменению кода группы и переносу группы в другую группу. В этих случаях нужно обработать и все подчиненные элементы.

Дополнительный эффект от реализации этого метода: при необходимости найти родителя
определенного элемента, находящегося на заданном уровне, нет необходимости итеративно получать ХХХ.Родитель и сравнивать его уровень с заданным. Достаточно взять (Уровень*5) левых символов и найти элемент с таким значением ключа.

Описанный механизм реализован в демонстрационной конфигурации, где можно сравнить производительность описанного метода со стандартным.

Если Вы можете дополнить этот материал или обнаружили ошибку, пожалуйста укажите это в комментариях или пишите автору.

Категория: Алгоритмические трюки | Добавил: MainGuru (19.02.2008) | Автор: Близниченко Дмитрий Александрович
Просмотров: 4349 | Рейтинг: 4.5/2 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа


Поиск

Где заработать

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Copyright MyCorp © 2024 Конструктор сайтов - uCoz