MYSQL中递归存储过程获取分层数据的性能

MYSQL中递归存储过程获取分层数据的性能,mysql,Mysql,我有一张桌子, 受雇者 emp_id int主键, emp_名称varchar50, mngr_id int 在这里,mngr_id要么为null,要么包含有效的emp_id。这样,它就形成了组织中员工的层次结构 为了遍历整个层次结构,我必须编写递归存储过程。在Oracle中,使用“连接方式”很容易。。从 所以问题是,如果层次结构的级别不超过10级,那么这种存储过程的性能影响是什么呢 还有其他方法可以达到同样的效果吗?关于最后一个问题:现在有一些不错的选择 您还应该考虑缓存中间表中递归的结果。如

我有一张桌子, 受雇者 emp_id int主键, emp_名称varchar50, mngr_id int

在这里,mngr_id要么为null,要么包含有效的emp_id。这样,它就形成了组织中员工的层次结构

为了遍历整个层次结构,我必须编写递归存储过程。在Oracle中,使用“连接方式”很容易。。从

所以问题是,如果层次结构的级别不超过10级,那么这种存储过程的性能影响是什么呢


还有其他方法可以达到同样的效果吗?

关于最后一个问题:现在有一些不错的选择

您还应该考虑缓存中间表中递归的结果。如果仅在更新层次结构表时更改该值,则递归性能的影响可以忽略不计

编辑:
就我个人而言,我会在我的应用程序的表示层中进行递归,例如在web服务器上。与SQL相比,这提供了更大的灵活性,您还可以使用会话或应用程序级缓存。不过,使用预先构造的DB表并通过触发器保持最新状态,永远不会让您拥有过时的缓存。

关于最后一个问题:这里有一些不错的选择

您还应该考虑缓存中间表中递归的结果。如果仅在更新层次结构表时更改该值,则递归性能的影响可以忽略不计

编辑:
就我个人而言,我会在我的应用程序的表示层中进行递归,例如在web服务器上。与SQL相比,这提供了更大的灵活性,您还可以使用会话或应用程序级缓存。不过,使用预先构造的DB表并通过触发器保持最新,永远不会留下过时的缓存。

Tomalak:。。。我会在我的应用程序的表示层中执行递归


这意味着每次递归发生时,都会从表示层向数据库服务器发送另一个调用。那会非常慢。

托马拉克:。。。我会在我的应用程序的表示层中执行递归


这意味着每次递归发生时,都会从表示层向数据库服务器发送另一个调用。这将非常缓慢。

一个相当简单的迭代邻接列表db服务器端解决方案:


一个相当简单的迭代邻接列表db服务器端解决方案:

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);