powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / рекурсивная функция (процедура)
18 сообщений из 43, страница 2 из 2
рекурсивная функция (процедура)
    #35302923
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
djvov
Код: plaintext
set @max_sp_recursion_depth= 3000 ;

Так напиши:
Код: plaintext
set session max_sp_recursion_depth= 255 
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303012
MAPA3OT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
djvovвообщем скрипт Nick Anikin выдал что Recursive limit 0 (as set by max_sp_recursion_depth variable) was exceeded by routine go
max_sp_recursion_depth надо увеличить? как его указать явно?
Код: plaintext
set @max_sp_recursion_depth= 3000 ;
перед выполнением - не помогло
скрипт MAPA3OT'a на небольшой вложенности работает верно, а на большой - нет.
В архиве дамп базы.
Если считать фотки экскаваторов
Код: plaintext
select selectSomething( 100695 , 3 );
, то будет 13, это верно.
А если считать самосвалы
Код: plaintext
select selectSomething( 100693 , 3 );
, то будет 133, хотя на самом деле там 248.

Ай-ай-ай, а врать не хорошо, что вернет этот запрос?
Код: plaintext
1.
2.
3.
4.
5.
6.
select * from foto_foto where
	 (top =  100693  and isgroup= 3 )
or (isgroup= 3  and top in (select id from foto_foto where top =  100693 ) )
or (isgroup= 3  and top in (select id from foto_foto where top in (select id from foto_foto where top =  100693 )) )
or (isgroup= 3  and top in (select id from foto_foto where top in (select id from foto_foto where top in (select id from foto_foto where top =  100693 ))) )
or (isgroup= 3  and top in (select id from foto_foto where top in (select id from foto_foto where top in (select id from foto_foto where top in (select id from foto_foto where top =  100693 )))) )
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303033
MAPA3OT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MAPA3OT djvov
Хотя, стоп, отставить, у вас точно такая функция?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
drop function if exists selectSomething;
delimiter //
create FUNCTION `selectSomething`(recPID INT, recType INT) RETURNS bigint( 20 )
BEGIN
	DECLARE ids BLOB;
  DECLARE tempIDScount INT;
  DECLARE IDScount INT;
  set tempIDScount =  0 ;
  set session group_concat_max_len =  3000000000 ;
	select group_concat(t.id), count(t.id) into ids, IDScount 
	from foto_foto t 
	where t.top = recPID or t.id=recPID;
	WHILE tempIDScount < IDScount DO
  	set tempIDScount = IDScount;
    select 
			group_concat(t.id), count(t.id) into ids, IDScount
		from 
			foto_foto t
		where 
			FIND_IN_SET(t.id,ids)	>  0 
			OR FIND_IN_SET(t.top,ids) > 0 ;
  END WHILE;
	return (select count(distinct id) from foto_foto where
	FIND_IN_SET(ID,ids)	>  0  and isGroup=recType);	
END//
delimiter ;
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303043
MAPA3OT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skol[
Минус один - многократный фуллскан таблицы (по числу вложенных уровней), т.е. тормоза

Фулскан - действительно тормоз прогресса, но я пока не понимаю как без него ибо
ваша функция к сожалению сложится (должна сложиться) на больших объемах данных, substring при работе с blob - проще сразу повеситься.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303067
MAPA3OT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MAPA3OT skol
Ну и еще один плевок в вас (я очень раздражительный перед похмельем), сравните:
допусти по всем уровням вложенности (пусть будет 10) всего 150 записей. а теперь сравните - полный перебор таблицы 10 раз со 150-ю быстрыми запросами.
Мне кажется, вы проигрываете в скорости.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303428
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мегазапрос
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
drop procedure if exists scan_proc;

delimiter |

create procedure scan_proc(p_id int, p_isgroup int, out cnt int)
begin
  set cnt =  0 ;
  set @ids = p_id;
  set @isgroup = p_isgroup;
  while not @ids is null do
     set @select_sql = concat(
        'select ',
        '  ( select count(*) from foto_foto where top in (', @ids, ') and isgroup = @isgroup ),',
        '  ( select group_concat(id) from foto_foto where top in (', @ids,') )',
        'into @k, @ids' 
      );  
     prepare scan_cnt from @select_sql;
     execute scan_cnt;
     set cnt = cnt + @k;
  end while;
  deallocate prepare scan_cnt;
end|
Код: plaintext
1.
call scan_proc( 100693 ,  3 , @a);
select @a;
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303440
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного оптимизировал:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
drop procedure if exists scan_proc;

delimiter |

create procedure scan_proc(p_id int, p_isgroup int, out cnt int)
begin
  set cnt =  0 , @ids = p_id;
  while not @ids is null do
     set @select_sql = concat(
        'select ',
        '  ( select count(*) from foto_foto where top in (', @ids, ') and isgroup = ', p_isgroup, ' ),',
        '  ( select group_concat(id) from foto_foto where top in (', @ids,') )',
        'into @k, @ids' 
      );  
     prepare scan_cnt from @select_sql;
     execute scan_cnt;
     set cnt = cnt + @k;
  end while;
  deallocate prepare scan_cnt;
end|
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303502
Фотография javajdbc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати о пти4каx. Если каталог довол;но стабил;ний,
то можно полухеные зна4ения записать в новой колонке.
Ина4е рыскать каждый раз -- сервер загнется.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303657
skol_at_home
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MAPA3OT MAPA3OT skol
Ну и еще один плевок в вас (я очень раздражительный перед похмельем), сравните:
допусти по всем уровням вложенности (пусть будет 10) всего 150 записей. а теперь сравните - полный перебор таблицы 10 раз со 150-ю быстрыми запросами.
Мне кажется, вы проигрываете в скорости.
Зависит от размера таблицы, от количества уровней и от реализации FIND_IN_SET. Для небольшого количества уровней / небольшой таблицы ваш метод выгодней (я применяю близкий метод, но с клиента (пых))
Опять же, 150 быстрых запросов в хранимке это совсем не тоже самое, что 150 запросов с клиента.
Теперь последний камень ;-) - у вас постепенно набирается множество всех узлов со всех уровней, если же, как я упоминал, включить определение количества картинов в цикл, можно использовать множество только текущего уровня. Т.е. у вас в большинстве запросов часть возвращаемого результата дублирует то, что уже было известно.

про реализацию на пыхе: здесь все можно сделать гораздо оптимальней:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
function getAllChildsIds($parent) {
    $ids = array();
    $childs = array($parent)
    while(count($childs)) {
       $childs = explode(',',db_get_value("select group_concat(id) from table1 where top in (".implode(',',$childs).")");
       $ids = array_merge($ids,$childs);
    }
    return $ids;
}
Т.е. получаем те же 10 запросов (что гораздо более критично, так как они идут с клиента), но запросы будут использовать индекс, и не проводится лишняя работа, причем идеально добавить индекс не просто по top, а INDEX(top,id). В этом случае будет читаться только индекс.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303660
MAPA3OT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
skol_at_home
Сначала о грустном для меня, если честно, то сам предпочитаю искать с клиента, а не на сервере (фиг его знает, когда GROUP_CONCAT захлебнется, да и вообще сервак лишний раз мучать - бред)

Теперь о веселом. Самое забавное, что мой метод рулит именно на больших объемах данных, но с маленьким числом уровней, не смотря на то, что мы по n-раз возвращаем одно и тоже. По поводу substring - вы меня вряд ли сможете убедить, ну тормознутый он, что тут сделаешь. А реализация Filed_in_set меня вообще не волнует, это мусевская родная функция и как она работает - проблемы муси, а не мои.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303662
MAPA3OT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О, а пока мы со skol пиписьками махались сзади тихо подошел xelaok и...

xelaok, я так с вами не играю это не честно и вообще это должен был написать я
А если честно, красиво, блин, и избегаем лишних проходов, и уменьшаем кол-во ненужной инфы, красиво.
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303710
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще немного посидел над запросом :)

Более быстрый вариант с правильным запросом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
drop procedure if exists scan_proc;

delimiter |

create procedure scan_proc(p_id int, p_isgroup int, out cnt int)
begin
  set cnt =  0 , @ids = p_id;
    while not @ids is null do
    set @select_sql = concat(
      'select group_concat(id), sum(isgroup = ', p_isgroup, ') '
      'from foto_foto ' 
      'where top in (', @ids,') '
      'into @ids, @k'
    );
    prepare scan_cnt from @select_sql;
    execute scan_cnt;
    set cnt = cnt + ifnull(@k,  0 );
  end while;
  deallocate prepare scan_cnt;
end

Такой же, но без prepare/execute:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
drop procedure if exists scan_proc2;

delimiter |

create procedure scan_proc2(p_id int, p_isgroup int, out cnt int)
begin
  declare ids blob default p_id;
  declare k int;

  set session group_concat_max_len =  256  *  1024 , cnt =  0 ;

  while not ids is null do
    select 
      group_concat(id),
      sum(isgroup = p_isgroup)
    from 
      foto_foto 
    where 
      find_in_set(top, ids) 
    into 
      ids, k;
			
    set cnt = cnt + ifnull(k,  0 );
  end while;
end
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303736
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
xelaokЕще немного посидел над запросом :)
Более быстрый вариант с правильным запросом:


оба с одинаковой скоростью работают?)
последний вариант спас мой сайт))
спасибо вам всем огромное, и с праздником!!!
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303749
xelaok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
djvovоба с одинаковой скоростью работают?)
неа, второй, без prepare, в раза 4 медленее...
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303794
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
xelaok djvovоба с одинаковой скоростью работают?)
неа, второй, без prepare, в раза 4 медленее...
а как замеряли? с помощью пхп я представляю как замерить скорость.. а с помощью одного мускуля как?
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #35303872
djvov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
да, и правда, первый вариант быстрей, где то в 2-3 раза, говорит мой замер.
единственное, что у меня не получилось его из пхп выполнить, а второй вариант нормально работает.

Код: plaintext
1.
2.
3.
4.
5.
6.
function getfotocount($id)
{	
	mysql_query("call scan_proc($id,3,@a);");
	$rez=mysql_fetch_array(mysql_query("select @a;"));
	return $rez[0];
}

выдает пустую строку
но если из клиента выполнять, то все верно говорит.


Код: plaintext
1.
2.
3.
4.
5.
6.
function getfotocount($id)
{	
	mysql_query("call scan_proc2($id,3,@a);");
	$rez=mysql_fetch_array(mysql_query("select @a;"));
	return $rez[0];
}

выдает количество нормально
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
рекурсивная функция (процедура)
    #39085723
Poprygun
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пример рекурсивного получения пути узла.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
DELIMITER $$

USE `itsd`$$

DROP PROCEDURE IF EXISTS `get_tree_path`$$

CREATE DEFINER=`root`@`%` PROCEDURE `get_tree_path`(_id INT, _path TEXT, _delimiter TEXT)
BEGIN
    DECLARE _parent_id INT ;
    DECLARE _nazvanie TEXT ;
    
	SET max_sp_recursion_depth = 10;
    SELECT 
        parent_id,
        nazvanie INTO _parent_id,
        _nazvanie 
    FROM
        tranzakciya_categoriya 
    WHERE id = _id ;
    IF (_path = '') 
    THEN SET _path = _nazvanie ;
    ELSE SET _path = CONCAT(_nazvanie, _delimiter, _path) ;
    END IF ;
    IF (_parent_id <> 0) 
    THEN CALL get_tree_path (_parent_id, _path, _delimiter) ;
    ELSE 
    SELECT 
        _path ;
    END IF ;
END$$

DELIMITER ;
...
Рейтинг: 0 / 0
рекурсивная функция (процедура)
    #39086651
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
18 сообщений из 43, страница 2 из 2
Форумы / MySQL [игнор отключен] [закрыт для гостей] / рекурсивная функция (процедура)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]