Консоль и функция рекурсивного запроса



Консоль предназначена для отладки и просмотра результатов выполнения РЕКУРСИВНОГО ЗАПРОСА в режиме 1С:Предприятие.
В консоли реализована универсальная функция для выполнения рекурсивных запросов.

Рекурсивный запрос — удобный способ выборки иерархических данных. Примеры рекурсивной выборки данных в 1С:Предприятие подробно рассмотрены в «Запрос против рекурсии или разузлование номенклатуры», «Транзитивное замыкание запросом» или далее по ссылкам в публикациях. Авторы предложили три варианта решения проблемы бесконечной рекурсии в графах с циклическими ссылками:

  1. Ограничивать количество рекурсивных циклов, предварительно вычислив их максимально возможное значение;
  2. Исключать циклические ссылки, проверяя пройденный путь, сохраняя его в виде строки кодов вершин графа;
  3. Исключать циклические ссылки, проверяя пройденный путь, сохраняя его во временной таблице.

Консоль позволяет опробовать любой из трех вариантов, для этого в консоли реализована специальная функция ВыполнитьРекурсивныйЗапрос(…). В функцию собраны идеи, описанные в вышеупомянутых публикациях:

  • Рекурсивный запрос разбивается на три пакетных подзапроса: Начальный, Рекурсивный, Итоговый;
  • Рекурсивный подзапрос повторяется в цикле. Условие выхода из рекурсивного цикла отличается и описано в особенностях функции;
  • Начальные и промежуточные данные сохраняются во временные таблицы с индексом шага рекурсивного цикла;В тексте подзапросов к именам временных таблиц добавляются служебные окончания «__НАЧАЛО_РЕКУРСИИ__» или «__КОНЕЦ_РЕКУРСИИ__». Служебные окончания автоматически заменяются на соответствующий индекс шага рекурсивного цикла.

Встроенная в консоль функция имеет особенности:

  • В конце начального подзапроса возвращается количество начальных данных;
  • В конце рекурсивного подзапроса возвращается количество данных, отобранное для итоговой выборки;
  • Рекурсивный цикл повторяется до тех пор, пока возвращаемое подзапросом число (количество записей) оказывается больше предыдущего числа (количества записей) — полученного на предыдущем шаге рекурсивного цикла.
  • ВНИМАНИЕ! Не используйте в текстах Начального или Рекурсивного подзапросов стандартную функцию 1С:Предприятие ПРЕДСТАВЛЕНИЕ(), это приводит к бесконечной рекурсии — зависанию системы!
&НаСервере 
Функция ВыполнитьРекурсивныйЗапрос(ЗНАЧ Параметр, ЗНАЧ Значение
, ЗНАЧ ТекстЗапросаИтог
, ЗНАЧ ТекстЗапросаРекурсия
 , ЗНАЧ ТекстЗапросаНачало
 , ЗНАЧ ШагРекурсииНачало = "__НАЧАЛО_РЕКУРСИИ__" // Подменяется в тексте запроса на предыдущий индекс шага рекурсии
 , ЗНАЧ ШагРекурсииКонец = "__КОНЕЦ_РЕКУРСИИ__" // Подменяется в тексте запроса на текущий индекс шага рекурсии
 , ЗНАЧ ЗапросМаксимальноеКоличествоЗаписей = "ВЫБРАТЬ 0;" // для предотвращения бесконечных рекурсий, 0 - без ограничений
, ЗНАЧ РежимОтладки = Ложь ) Экспорт

    Если СокрЛП(ШагРекурсииНачало)="" тогда
        ШагРекурсииНачало = "__НАЧАЛО_РЕКУРСИИ__"
    КонецЕсли;

    Если
СокрЛП(ШагРекурсииКонец)="" тогда
        ШагРекурсииКонец = "__КОНЕЦ_РЕКУРСИИ__"
    КонецЕсли; ТекВремя = ТекущаяДата();

    Если РежимОтладки тогда
        Сообщить(Формат(ТекВремя, "ДЛФ=T") + ", СТАРТ запроса",СтатусСообщения.Информация);
    КонецЕсли;

    Запрос = Новый Запрос();
 
    // Менеджер временных таблиц необходим для сохранения в памяти промежуточных таблиц рекурсии

    Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц();

    // ИндексРекурсии для генерации шага рекурсии в имени таблицы
    ИндексРекурсии = 0;

    // Если начальный запрос пустой, выполним только итоговый запрос

    Если ТекстЗапросаНачало<>Неопределено И ТекстЗапросаНачало<>"" тогда

        // Выход из рекурсии, когда количество записей в итоговой теблице перестанет прибавляться

        СтароеКоличествоЗаписей = 0;
        НовоеКоличествоЗаписей = 0;

        // Заменим в начальном подзапросе имена таблиц, указав начальный шаг рекрсии
        Запрос.Текст = СтрЗаменить(ТекстЗапросаНачало, ШагРекурсииНачало, Формат(ИндексРекурсии, "ЧН=0; ЧГ=0"));

        Если Параметр<>Неопределено И Параметр<>"" тогда
            Запрос.УстановитьПараметр(Параметр, Значение);
        КонецЕсли;

        // Выполним начальный подзапрос
        Попытка РезультатЗапроса = Запрос.Выполнить();
            Исключение ВызватьИсключение "Ошибка в НАЧАЛЬНОМ подзапросе: " + ОписаниеОшибки() + " !ВНИМАНИЕ! Ключевое слово '"+ШагРекурсииНачало+"' заменено на '"+Формат(ИндексРекурсии, "ЧН=0; ЧГ=0")+"'";
        КонецПопытки
;

        // Если рекурсивный запрос пустой, выполним только итоговый запрос
        Если ТекстЗапросаРекурсия<>Неопределено И ТекстЗапросаРекурсия<>"" тогда

            // Определим указанное в парамтрах максимальное допустимое количество шагов рекурсивного подзапроса
            МаксимальноеКоличествоРекурсий=0;

            Если ЗапросМаксимальноеКоличествоЗаписей<>Неопределено И ЗапросМаксимальноеКоличествоЗаписей<>"" тогда
                ЗапросКоличества = Новый Запрос();
                ЗапросКоличества.Текст = ЗапросМаксимальноеКоличествоЗаписей;

                Попытка

                    РезультатЗапросаКоличества = ЗапросКоличества.Выполнить();
                    ВыборкаДетальныеЗаписи = РезультатЗапросаКоличества.Выбрать();

                    Если ВыборкаДетальныеЗаписи.Следующий() Тогда
                   
                        МаксимальноеКоличествоРекурсий = ВыборкаДетальныеЗаписи.Получить(0);
                   
                        Если ТипЗнч(МаксимальноеКоличествоРекурсий)<>Тип("Число") тогда
                            Сообщить("Запрос '"+ЗапросМаксимальноеКоличествоЗаписей+"' для ограничения максимального количества записей должен быть пустым, либо возвращать число!" ,СтатусСообщения.Внимание);
                            МаксимальноеКоличествоРекурсий=1;
                        КонецЕсли;
                    КонецЕсли;
                Исключение
                    Сообщить("Запрос для ограничения максимального количества записей рекурсии выполнен с ошибкой:" + ОписаниеОшибки() ,СтатусСообщения.Внимание);
                    МаксимальноеКоличествоРекурсий=1;
                КонецПопытки
;
            КонецЕсли;

            // Определим количество записей полученное в начальном подзапросе
            ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

            Если
ВыборкаДетальныеЗаписи.Следующий() Тогда
           
                НовоеКоличествоЗаписей = ВыборкаДетальныеЗаписи.Получить(0);
           
                Если
ТипЗнч(НовоеКоличествоЗаписей)<>Тип("Число") тогда
                    Сообщить("Начальный подзапрос должен возвращать количество записей в начальной выборке! НАПРИМЕР: 'ВЫБРАТЬ КОЛИЧЕСТВО (*) ИЗ ИтоговаяТаблица"+ШагРекурсииНачало+"' " ,СтатусСообщения.Внимание);
                    НовоеКоличествоЗаписей=1;
                КонецЕсли;
            КонецЕсли;

            Если РежимОтладки тогда
                ТекВремя=ТекущаяДата();
                Сообщить(Формат(ТекВремя, "ДЛФ=T") + ", выполнен НАЧАЛЬНЫЙ подзапрос, количество записей: "+НовоеКоличествоЗаписей,СтатусСообщения.Информация);
            КонецЕсли
;

            // Основной Ц И К Л рекурсии, пока увеличивается количество записей
            Пока НовоеКоличествоЗаписей > СтароеКоличествоЗаписей
                И (МаксимальноеКоличествоРекурсий=0 ИЛИ НовоеКоличествоЗаписей < МаксимальноеКоличествоРекурсий) цикл

                // Сдвигаем количество записей и индекс рекурсии
                СтароеКоличествоЗаписей = НовоеКоличествоЗаписей;
                ИндексРекурсии = ИндексРекурсии + 1;

                // Заменим в рекурсивном подзапросе имена таблиц, указав текущий шаг рекрсии

                Запрос.Текст = СтрЗаменить(ТекстЗапросаРекурсия, ШагРекурсииНачало, Формат(ИндексРекурсии-1, "ЧН=0; ЧГ=0"));
                Запрос.Текст = СтрЗаменить(Запрос.Текст, ШагРекурсииКонец, Формат(ИндексРекурсии, "ЧН=0; ЧГ=0"));

                Если
Параметр<>Неопределено И Параметр<>"" тогда
                    Запрос.УстановитьПараметр(Параметр, Значение);
                КонецЕсли;

                // Выполним рекурсивный подзапрос
                Попытка
                    РезультатЗапроса = Запрос.Выполнить();
                Исключение
                    ВызватьИсключение "Ошибка в РЕКУРСИВНОМ подзапросе: " + ОписаниеОшибки() + " !ВНИМАНИЕ! Ключевые слова: '"+ШагРекурсииНачало+"' заменено на '"+Формат(ИндексРекурсии-1, "ЧН=0; ЧГ=0")+"', " + " '"+ШагРекурсииКонец+"' заменено на '"+Формат(ИндексРекурсии, "ЧН=0; ЧГ=0")+"'";
                КонецПопытки
;

                ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

                // Определим новое количество записей, полученное в рекурсивном подзапросе
                Если ВыборкаДетальныеЗаписи.Следующий() Тогда
               
                    НовоеКоличествоЗаписей = ВыборкаДетальныеЗаписи.Получить(0);

                    Если ТипЗнч(НовоеКоличествоЗаписей)<>Тип("Число") тогда
                        Сообщить("Рекурсивный подзапрос должен возвращать количество записей в итоговой выборке! НАПРИМЕР: 'ВЫБРАТЬ КОЛИЧЕСТВО (*) ИЗ ИтоговаяТаблица"+ШагРекурсииНачало+"' " ,СтатусСообщения.Внимание);
                        НовоеКоличествоЗаписей=1;
                    КонецЕсли;
                КонецЕсли;

                Если РежимОтладки И ТекВремя<>ТекущаяДата() тогда
                    ТекВремя=ТекущаяДата();
                    Сообщить(Формат(ТекВремя, "ДЛФ=T") + ", выполнен " + ИндексРекурсии + " РЕКУРСИВНЫЙ подзапрос, количество записей: "+НовоеКоличествоЗаписей,СтатусСообщения.Информация);
                КонецЕсли
;
           
            КонецЦикла
;
       
        КонецЕсли
;
    КонецЕсли;

    // Заменим в итоговом подзапросе имена таблиц, указав конечный шаг рекрсии
    Запрос.Текст = СтрЗаменить(ТекстЗапросаИтог, ШагРекурсииКонец, Формат(ИндексРекурсии, "ЧН=0; ЧГ=0"));

    Если Параметр<>Неопределено И Параметр<>"" тогда
        Запрос.УстановитьПараметр(Параметр, Значение);
    КонецЕсли
;

    // Выполним итоговый подзапрос
    Попытка
        РезультатЗапроса = Запрос.Выполнить();
    Исключение
        ВызватьИсключение "Ошибка в ИТОГОВОМ подзапросе: " + ОписаниеОшибки() + " !ВНИМАНИЕ! Ключевое слово '"+ШагРекурсииКонец+"' заменено на '"+Формат(ИндексРекурсии, "ЧН=0; ЧГ=0")+"'";
    КонецПопытки
;

    Если
РежимОтладки тогда ТекВремя=ТекущаяДата();
        Сообщить(Формат(ТекВремя, "ДЛФ=T") + ", выполнен ИТОГОВЫЙ подзапрос",СтатусСообщения.Информация);
    КонецЕсли;

    Возврат РезультатЗапроса;
КонецФункции

Консоль выполняет рекурсивный запрос в одном из двух режимов:

  • “Выполнить” — в стандартном режиме;
  • “Выполнить запрос с указанием времени” — с указанием времени выполнения рекурсивного запроса в формате часы:минуты:секунды.

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

/////////////////////////////////////////////////////////////////////////////// 
// ФОРМИРОВАНИЕ ТЕСТОВОЙ ТАБЛИЦЫ

ВЫБРАТЬ 0 КАК объект, 1 КАК субъект , "00" КАК с_объект, "01" КАК с_субъект
ПОМЕСТИТЬ таблица10
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 2 КАК субъект , "00" КАК с_объект, "02" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 3 КАК субъект , "00" КАК с_объект, "03" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 4 КАК субъект , "00" КАК с_объект, "04" КАК с_субъект
ОБЪЕДИНИТЬ
ВЫБРАТЬ 0 КАК объект, 5 КАК субъект , "00" КАК с_объект, "05" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 6 КАК субъект , "00" КАК с_объект, "06" КАК с_субъект
ОБЪЕДИНИТЬ
ВЫБРАТЬ 0 КАК объект, 7 КАК субъект , "00" КАК с_объект, "07" КАК с_субъект
ОБЪЕДИНИТЬ
ВЫБРАТЬ 0 КАК объект, 8 КАК субъект , "00" КАК с_объект, "08" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 9 КАК субъект , "00" КАК с_объект, "09" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 10 КАК субъект , "00" КАК с_объект, "10" КАК с_субъект;

ВЫБРАТЬ 100+родитель.субъект КАК объект, 200+потомок.субъект КАК субъект
,
"1"+родитель.с_субъект КАК с_объект, "2"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ
таблица100 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;

ВЫБРАТЬ 200+родитель.субъект КАК объект, 300+потомок.субъект КАК субъект
, "2"+родитель.с_субъект КАК с_объект, "3"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ таблица1000 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;

ВЫБРАТЬ 300+родитель.субъект КАК объект, 400+потомок.субъект КАК субъект
, "3"+родитель.с_субъект КАК с_объект, "4"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ
таблица10000 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;

ВЫБРАТЬ
400+родитель.субъект КАК объект, 500+потомок.субъект КАК субъект
,
"4"+родитель.с_субъект КАК с_объект, "5"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ таблица100000 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;

ВЫБРАТЬ 500+родитель.субъект КАК объект, 600+потомок.субъект КАК субъект
,
"5"+родитель.с_субъект КАК с_объект, "6"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ
таблица1000000 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;

ВЫБРАТЬ
000+объект КАК объект, 100+субъект КАК субъект , "0"+с_объект КАК с_объект
,
"1"+с_субъект КАК с_субъект ПОМЕСТИТЬ таблица ИЗ таблица10
ОБЪЕДИНИТЬ
ВСЕ ВЫБРАТЬ * ИЗ таблица100
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ * ИЗ таблица1000
ОБЪЕДИНИТЬ
ВСЕ ВЫБРАТЬ * ИЗ таблица10000
ОБЪЕДИНИТЬ
ВСЕ ВЫБРАТЬ ПЕРВЫЕ 0 * ИЗ таблица100000
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ПЕРВЫЕ 0 * ИЗ таблица1000000

// Циклическая ссылка

//0// ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 301 КАК объект, 101 КАК субъект
//0// , "301" КАК с_объект, "101" КАК с_субъект

ИНДЕКСИРОВАТЬ ПО объект, субъект;

УНИЧТОЖИТЬ
таблица10;
УНИЧТОЖИТЬ таблица100;
УНИЧТОЖИТЬ таблица1000;
УНИЧТОЖИТЬ таблица10000;
УНИЧТОЖИТЬ таблица100000;
УНИЧТОЖИТЬ таблица1000000;

// КОНЕЦ ФОРМИРОВАНИЯ ТЕСТОВОЙ ТАБЛИЦЫ
///////////////////////////////////////////////////////////////////////////////

Пример начального подзапроса

/////////////////////////////////////////////////////////////////////////////// 
// НАЧАЛЬНЫЙ ПОДЗАПРОС

ВЫБРАТЬ
объект, субъект , с_объект, с_субъект
, 1 КАК уровень , "."+с_объект+"."+с_субъект+"." КАК путь
, "" КАК старый_путь
ПОМЕСТИТЬ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__
ИЗ таблица
ГДЕ
объект=0;

//--------- служебная счасть ---------//


// 1.1. ПРОЙДЕННЫЕ УЗЛЫ
// для исключения бесконечной рекурсии
//3//ВЫБРАТЬ РАЗЛИЧНЫЕ объект, субъект
//3//ПОМЕСТИТЬ ПройденныеУзлы__НАЧАЛО_РЕКУРСИИ__
//3//ИЗ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__

//3//ОБЪЕДИНИТЬ
//3//ВЫБРАТЬ субъект КАК объект, субъект
//3//ИЗ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__

//3//ИНДЕКСИРОВАТЬ ПО 2,1;


// 1.2. ИТОГОВЫЕ ДАННЫЕ
ВЫБРАТЬ * ПОМЕСТИТЬ ИтоговаяТаблица__НАЧАЛО_РЕКУРСИИ__
ИЗ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__;

// 1.4. КОЛИЧЕСТВО ЗАПИСЕЙ

ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ ИтоговаяТаблица__НАЧАЛО_РЕКУРСИИ__;

// КОНЕЦ НАЧАЛЬНОГО ПОДЗАПРОСА
///////////////////////////////////////////////////////////////////////////////

Пример рекурсивного подзапроса

/////////////////////////////////////////////////////////////////////////////// 
// РЕКУРСИВНЫЙ ПОДЗАПРОС


ВЫБРАТЬ таблица.*, рекурсия.уровень+1 КАК уровень
, рекурсия.путь+таблица.с_субъект+"." КАК путь
,
рекурсия.путь КАК старый_путь
ПОМЕСТИТЬ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__
ИЗ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__ КАК рекурсия
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
таблица ПО таблица.объект=рекурсия.субъект

// соединенние для исключения бесконечной рекурсии
//3//ЛЕВОЕ СОЕДИНЕНИЕ ПройденныеУзлы__НАЧАЛО_РЕКУРСИИ__ ПройденныеУзлы
//3// ПО ПройденныеУзлы.субъект=таблица.объект
//3// И ПройденныеУзлы.объект=таблица.субъект
ГДЕ ИСТИНА
//1// И рекурсия.уровень<8 // ограниечение количества уровней //2// И НЕ рекурсия.путь ПОДОБНО "%."+таблица.с_субъект+".%" //3// И ПройденныеУзлы.субъект ЕСТЬ NULL ;

//--------- служебная счасть ---------//
// 2.1. ПРОЙДЕННЫЕ УЗЛЫ
// для исключения бесконечной рекурсии //3//ВЫБРАТЬ РАЗЛИЧНЫЕ ПройденныеУзлы.объект, Рекурсия.субъект //3//ПОМЕСТИТЬ ПройденныеУзлы__КОНЕЦ_РЕКУРСИИ__ //3//ИЗ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__ Рекурсия //3//ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПройденныеУзлы__НАЧАЛО_РЕКУРСИИ__ ПройденныеУзлы ПО ПройденныеУзлы.субъект=Рекурсия.объект //3//ОБЪЕДИНИТЬ //3//ВЫБРАТЬ субъект КАК объект, субъект ИЗ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__ //3//ИНДЕКСИРОВАТЬ ПО 2,1;
// 2.2. ИТОГОВЫЕ ДАННЫЕ ВЫБРАТЬ * ПОМЕСТИТЬ ИтоговаяТаблица__КОНЕЦ_РЕКУРСИИ__ ИЗ ИтоговаяТаблица__НАЧАЛО_РЕКУРСИИ__
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ * ИЗ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__ ;

// 2.3. ОСВОБОЖДЕНИЕ ПАМЯТИ
//3//УНИЧТОЖИТЬ ПройденныеУзлы__НАЧАЛО_РЕКУРСИИ__;
УНИЧТОЖИТЬ
РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__;
УНИЧТОЖИТЬ ИтоговаяТаблица__НАЧАЛО_РЕКУРСИИ__;

// 2.4. КОЛИЧЕСТВО ЗАПИСЕЙ

ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ ИтоговаяТаблица__КОНЕЦ_РЕКУРСИИ__;

// КОНЕЦ РЕКУРСИВНОГО ПОДЗАПРОСА
///////////////////////////////////////////////////////////////////////////////

Пример итогового подзапроса

/////////////////////////////////////////////////////////////////////////////// 
// ИТОГОВЫЙ ПОДЗАПРОС

ВЫБРАТЬ //ПЕРВЫЕ 10
КОЛИЧЕСТВО(*)
// *
ИЗ ИтоговаяТаблица__КОНЕЦ_РЕКУРСИИ__
//УПОРЯДОЧИТЬ ПО объект, субъект, путь
;

//--------- служебная счасть ---------//
// 3.3. ОСВОБОЖДЕНИЕ ПАМЯТИ
//3//УНИЧТОЖИТЬ ПройденныеУзлы__КОНЕЦ_РЕКУРСИИ__;
УНИЧТОЖИТЬ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__;
УНИЧТОЖИТЬ ИтоговаяТаблица__КОНЕЦ_РЕКУРСИИ__;
УНИЧТОЖИТЬ таблица;

// конец ИТОГОВЫЙ ПОДЗАПРОС
///////////////////////////////////////////////////////////////////////////////

В подзапросах отмечены комментариями:
//0// — пример циклической ссылки — ВНИМАНИЕ! Возможно зависание системы! Не убирайте данный комментарий, если в рекурсивный запрос не включен механизм исключения циклических ссылок.
//1// — пример ограничения количества шагов рекурсивного цикла.
//2// — пример исключения циклических ссылок через проверку пройденного пути сохраненного в виде строки кодов вершин графа.
//3// — (в разных местах запроса) пример исключения циклических ссылок через проверку пройденного пути сохраненного во временную таблицу.

Время работы рекурсивной выборки в зависимости от количества итоговых записей

Тест файловой СУБД, Core2Duo 2.40GHz, 4ГБ ОЗУ

 Файл-серверная статистика

Кол-во

  записей 

 Время выполнение рекурсивного

запроса (сек.)

Без

 контроля

 Контроль и сохранение

пройденного пути

в строке в таблице
111 110 5 6 37
121 110 6 7 43
211 110 10 11 81
311 110 15 16 124
411 110 20 21 172
511 110 23 25 211
711 110 32 35 257
911 110 41 44 385
 1 111 110
49 54 473

Тест на http://demo.1c.ru

 Тест на demo.1c.ru

 

Кол-во

  записей 

 Время выполнение рекурсивного

запроса (сек.)

Без

 контроля

 Контроль и сохранение

пройденного пути

в строке в таблице
111 110 1 2 7
121 110 1 2 7
211 110 1 4 9
311 110 3 5 9
411 110 3 6 11
511 110 4 7 12
711 110 5 9 15
911 110 10 11 17
 1 111 110
11 11 20

 

 

 

 

 

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *