2012-04-27 2 views
2

나는 (매우 동적 인) 트리 구조를 MySQL 데이터베이스에 저장하기 위해 인접리스트 모델을 사용하고있다. 가급적 저장된 루틴에 대한 단일 호출을 통해 주어진 노드의 모든 자손을 선택하는 방법이 필요합니다. 중첩 된 세트 모델을 사용하면이 작업을 쉽게 수행 할 수 있지만 다른 작업은 매우 어려워집니다. 따라서 불행히도 나를위한 옵션이 아닙니다. 여기에 지금까지있어 무엇 :트리 노드의 모든 자손 선택

DELIMITER // 

CREATE PROCEDURE get_descendants(node_id INT) 
    BEGIN 

    DROP TEMPORARY TABLE IF EXISTS descendants; 
    CREATE TEMPORARY TABLE descendants (id INT, name VARCHAR(100), parent_id INT); 

    INSERT INTO descendants 
     SELECT * 
     FROM nodes 
     WHERE parent_id <=> node_id; 

    -- ...? 

    END// 

DELIMITER ; 

아이디어는 내가 잎에 도달 할 때까지 아래로 자손 테이블에 자녀를 추가 시추를 유지하는 것입니다. 그러면 절차 외에서 임시 테이블에 액세스 할 수 있습니다. (실제로 저장된 함수에서 결과 집합을 반환 할 수 없습니다 빤다.)

어떻게 든 결과를 반복하고 각 행에 대해 새 SELECT 문을 발급해야합니다. 나는 커서가 여기에 도움이 될 수 있다고 읽었지만, 나는 어떻게 보이지 않는다. 커서를 사용하면 모든 것을 앞에서 선택하고 반복해야합니다.

+0

중첩 세트 만 사용할 수있는 것은 아닙니다. 클로저 테이블도 살펴볼 가치가 있습니다. – eggyal

+0

사실, 오늘 막 폐쇄 테이블을 발견했습니다! 그들은 유망한 것처럼 보이지만 이동 작업을 잘 처리하지 못합니다. http://www.mysqlperformanceblog.com/2011/02/14/moving-subtrees-in-closure-table/ 그런 의미에서, 그들은 일종의 중첩 세트입니다. 나는 계속 공부할 것이다. – Metaphile

+0

귀하의 필요에 맞는 적절한 데이터 구조를 선택하는 것은 모든 솔루션이 공간에 대해 다른 방식으로 시간을 절약하기 때문에 다양한 유형의 작업을 수행해야하는 빈도를 이해하는 데 있습니다. 그래프가 상당히 정적이며 경로를 통해 경로를 검사해야하는 경우 인접 목록이 최선의 선택이 아닐 수 있습니다. 그러나 그래프가 매우 동적이어서 주어진 노드의 바로 인접한 이웃보다 많은 것을 검사 할 필요가 거의없는 이상적인 솔루션 일 수 있습니다. – eggyal

답변

0

최대 read : write입니다. 독서의 비율이 매우 높다면, 임시 관계가 아닌 완전한 관계를 만드는 것이 매우 도움이 될 것입니다.

의사 접근법 (아니 실제 코드!) :

1. node(1) has child node(2) 
    -> Insert a row with (parent_id = 1, child_id = 2, direct = True) 

2. node(2) has child node(3) 
    -> Insert a row with (parent_id = 2, child_id = 3, direct = True) 
    -> Choose all ascendants of node(2) 
    -> Ascendants of node(2) : [node(1)] 
    -> Insert a row with (parent_id = 1, child_id = 3, direct = False) 

3. To retrieve all descendants of node(1) 
    -> SELECT child_id FROM [table] WHERE parent_id = 1; 

4. To retrieve children of node(1) 
    -> SELECT child_id FROM [table] WHERE parent_id = 1 AND direct = True; 

5. To retrieve all ascendants of node(3) 
    -> SELECT parent_id FROM [table] WHERE child_id = 3; 

6. To retrieve parent of node(3) 
    -> SELECT parent_id FROM [table] WHERE child_id = 3 AND direct = True; 

+-----------+----------+--------+ 
| parent_id | child_id | direct | 
+-----------+----------+--------| 
|   1 |  2 | True | 
|   1 |  3 | False | 
|   2 |  3 | True | 
.... 
+-----------+----------+--------+ 
Index 1 on (parent_id, direct) 
Index 2 on (child_id, direct) 

이 approche 관계를 업데이트하는 동안 나쁜 성능을 가지고있다. 자신의 책임하에 사용하십시오.

관련 문제