Performance of recursive stored procedures in MYSQL to get hierarchical data

前端 未结 3 1499
死守一世寂寞
死守一世寂寞 2021-01-16 06:56

I have table employee like,
employee ( emp_id int primary key, emp_name varchar(50), mngr_id int)

and here mngr_id would either null or contain valid emp_id. Th

相关标签:
3条回答
  • 2021-01-16 07:34

    Regarding the last question: There are a few nice options at "What is the most efficient/elegant way to parse a flat table into a tree?"

    You should also consider caching the result of the recursion in an intermediate table. If you change that only on update to your hierarchy table, the recursion performance hit will be negligible.

    EDIT: Personally I would do the recursion in the presentation layer of my app, for example on the web server. This provides greater flexibility compared to what can be achieved in SQL, and you can also use session or application level caching. (Using a pre-constructed DB table that is kept up to date with a trigger never leaves you with an outdated cache, though.)

    0 讨论(0)
  • 2021-01-16 07:36

    Tomalak: " ... I would do the recursion in the presentation layer of my app ... "

    This would mean every time the recursion happened another call is sent to the database server from the presentation layer. That would be incredibly slow.

    0 讨论(0)
  • 2021-01-16 07:47

    a fairly simple iterative adjacency list db server side solution: http://pastie.org/1056977

    delimiter ;
    
    drop procedure if exists employee_hier;
    
    delimiter #
    
    create procedure employee_hier
    (
    in p_emp_id smallint unsigned
    )
    begin
    
    declare p_done tinyint unsigned default(0);
    declare p_depth smallint unsigned default(0);
    
    create temporary table hier(
     boss_id smallint unsigned, 
     emp_id smallint unsigned, 
     depth smallint unsigned
    )engine = memory;
    
    insert into hier values (null, p_emp_id, p_depth);
    
    /* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */
    
    create temporary table emps engine=memory select * from hier;
    
    while p_done <> 1 do
    
        if exists( select 1 from employee e inner join hier on e.boss_id = hier.emp_id and hier.depth = p_depth) then
    
            insert into hier select e.boss_id, e.emp_id, p_depth + 1 
                from employee e inner join emps on e.boss_id = emps.emp_id and emps.depth = p_depth;
    
            set p_depth = p_depth + 1;          
    
            truncate table emps;
            insert into emps select * from hier where depth = p_depth;
    
        else
            set p_done = 1;
        end if;
    
    end while;
    
    select 
     e.emp_id,
     e.name as emp_name,
     b.emp_id as boss_emp_id,
     b.name as boss_name,
     hier.depth
    from 
     hier
    inner join employee e on hier.emp_id = e.emp_id
    inner join employee b on hier.boss_id = b.emp_id;
    
    drop temporary table if exists hier;
    drop temporary table if exists emps;
    
    end #
    
    delimiter ;
    
    
    call employee_hier(1);
    call employee_hier(3);
    
    0 讨论(0)
提交回复
热议问题