2008-10-21 9 views
1

J'ai employé de table comme,
employé ( emp_id int clé primaire, emp_name varchar (50), mngr_id int)Performance des procédures récursives stockées dans MYSQL pour obtenir des données hiérarchiques

et ici mngr_id serait nul ou contiendrait emp_id valide. De cette façon, il forme la hiérarchie des employés dans l'organisation.

Pour parcourir toute la hiérarchie, j'ai dû écrire la procédure stockée récursive. (dans Oracle, il est facile d'utiliser CONNECT BY .. START WITH)

Donc la question est que quel est l'impact sur les performances d'une telle procédure stockée étant donné que le niveau de la hiérarchie ne dépasserait pas 10 niveaux!

Existe-t-il un autre moyen de parvenir au même résultat?

Répondre

1

En ce qui concerne la dernière question: Il y a quelques bonnes options à "What is the most efficient/elegant way to parse a flat table into a tree?"

Vous devriez également considérer la mise en cache le résultat de la récursion dans une table intermédiaire. Si vous modifiez cela uniquement lors de la mise à jour de votre table hiérarchique, la performance de la récursivité sera négligeable.

EDIT: Personnellement, je ferais la récursivité dans la couche de présentation de mon application, par exemple sur le serveur Web. Cela offre une plus grande flexibilité par rapport à ce qui peut être réalisé en SQL, et vous pouvez également utiliser la mise en cache de session ou d'application. (L'utilisation d'une table DB pré-construite qui est mise à jour avec un déclencheur ne vous laisse jamais avec un cache obsolète, cependant.)

0

Tomalak: "... Je ferais la récursivité dans la couche de présentation de mon application Cela signifierait que chaque fois que la récursivité se produirait, un autre appel serait envoyé au serveur de base de données à partir de la couche de présentation. Ce serait incroyablement lent.

3

une liste de contiguïté itérative assez simple solution côté serveur db: 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); 
Questions connexes