복붙노트

[SQL] 어떻게 SQL에서 데이터 트리를 대표하는?

SQL

어떻게 SQL에서 데이터 트리를 대표하는?

나는 나무와의 TreeNode에서 결합되는 데이터 트리 구조를 쓰고 있어요. 트리 루트와 데이터에 대한 최고 수준의 작업이 포함됩니다. 나는 창문 형성에 나는 트 리뷰에 나무를 결합 할 수있는 트리를 제공하기 위해 UI 라이브러리를 사용하고 있습니다.

나는 DB에서이 트리 노드를 저장해야합니다. 어떤 것은 나무를 저장하고 다음과 같은 기능을 얻을 수있는 가장 좋은 방법이 될 것입니다 :

나는이 개 아이디어를 가지고 있었다. 먼저 테이블에서 하나의 라이너로 데이터를 직렬화하는 것이다. 두 번째는 테이블에 저장하지만 데이터 엔티티로 이동할 때 다음, 나는 변경 노드에서 테이블에 행 상태를 잃어 버릴 것이다.

어떤 아이디어?

해결법

  1. ==============================

    1.가장 쉬운 구현은 인접리스트 구조입니다 :

    가장 쉬운 구현은 인접리스트 구조입니다 :

    id  parent_id  data
    

    그것은 MySQL이 부족 재귀 쿼리를 실행할 수있는 능력을 필요로하기 때문에, 일부 데이터베이스는, 특히 MySQL은,이 모델을 취급 몇 가지 문제가 있습니다.

    또 다른 모델은 중첩 된 세트입니다 :

    id lft rgt data
    

    LFT RGT와 계층 구조를 정의하는 임의의 값이있는 곳 (하위의 LFT는 RGT 모든 부모의 LFT 내에 있어야 RGT)

    이것은 재귀 쿼리를 필요로하지 않지만, 느리고 어렵게 유지.

    그러나, MySQL은이는 공간 능력을 사용하여 향상시킬 수있다.

    내 블로그에이 문서를 참조하십시오

    더 많은 설명을 자세히 설명.

  2. ==============================

    2.나는 몇 가지 대안에 대해 설명 SQL-반 패턴에 대한이 slidshare를 북마크했습니다 http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back?src=embed

    나는 몇 가지 대안에 대해 설명 SQL-반 패턴에 대한이 slidshare를 북마크했습니다 http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back?src=embed

    거기에서 권장은 (는 슬라이드에 설명 된 것) 클로저 표를 사용하는 것입니다.

    다음은 요약 (슬라이드 77)입니다 :

                      | Query Child | Query Subtree | Modify Tree | Ref. Integrity
    Adjacency List    |    Easy     |     Hard      |    Easy     |      Yes
    Path Enumeration  |    Easy     |     Easy      |    Hard     |      No
    Nested Sets       |    Hard     |     Easy      |    Hard     |      No
    Closure Table     |    Easy     |     Easy      |    Easy     |      Yes
    
  3. ==============================

    3.나는 아무도 아마 표준 SQL에서 나무와 작업의 가장 빠른 방법입니다 구체화 된 경로 솔루션을 언급 없음을 놀라게하고있다.

    나는 아무도 아마 표준 SQL에서 나무와 작업의 가장 빠른 방법입니다 구체화 된 경로 솔루션을 언급 없음을 놀라게하고있다.

    이 방법에서, 트리의 모든 노드는 노드 루트에서 전체 경로가 저장되는 열 경로를 가지고있다. 이것은 매우 간단하고 빠른 쿼리를 포함한다.

    예제 테이블 노드에서보세요 :

    +---------+-------+
    | node_id | path  |
    +---------+-------+
    | 0       |       |
    | 1       | 1     |
    | 2       | 2     |
    | 3       | 3     |
    | 4       | 1.4   |
    | 5       | 2.5   |
    | 6       | 2.6   |
    | 7       | 2.6.7 |
    | 8       | 2.6.8 |
    | 9       | 2.6.9 |
    +---------+-------+
    

    노드 x의 아이들을 취득하기 위하여는, 당신은 다음과 같은 쿼리를 작성할 수 있습니다 :

    SELECT * FROM node WHERE path LIKE CONCAT((SELECT path FROM node WHERE node_id = x), '.%')
    

    에서 LIKE 절을 빠르게 수행하기 위해, 열 경로가 색인되어야 함을 명심하십시오.

  4. ==============================

    4.당신의 PostgreSQL을 사용하는 경우 ltree를 사용할 수는있는 contrib 확장의 패키지는 트리 데이터 구조를 구현하는 (기본적으로 제공됩니다).

    당신의 PostgreSQL을 사용하는 경우 ltree를 사용할 수는있는 contrib 확장의 패키지는 트리 데이터 구조를 구현하는 (기본적으로 제공됩니다).

    워드 프로세서 :

    CREATE TABLE test (path ltree);
    INSERT INTO test VALUES ('Top');
    INSERT INTO test VALUES ('Top.Science');
    INSERT INTO test VALUES ('Top.Science.Astronomy');
    INSERT INTO test VALUES ('Top.Science.Astronomy.Astrophysics');
    INSERT INTO test VALUES ('Top.Science.Astronomy.Cosmology');
    INSERT INTO test VALUES ('Top.Hobbies');
    INSERT INTO test VALUES ('Top.Hobbies.Amateurs_Astronomy');
    INSERT INTO test VALUES ('Top.Collections');
    INSERT INTO test VALUES ('Top.Collections.Pictures');
    INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy');
    INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy.Stars');
    INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy.Galaxies');
    INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy.Astronauts');
    CREATE INDEX path_gist_idx ON test USING GIST (path);
    CREATE INDEX path_idx ON test USING BTREE (path);
    

    당신은 쿼리를 같이 할 수 있습니다 :

    ltreetest=> SELECT path FROM test WHERE path <@ 'Top.Science';
                    path
    ------------------------------------
     Top.Science
     Top.Science.Astronomy
     Top.Science.Astronomy.Astrophysics
     Top.Science.Astronomy.Cosmology
    (4 rows)
    
  5. ==============================

    5.그것은 당신이 쿼리와 데이터를 업데이트 할 방법에 따라 달라집니다. 당신은 하나의 행에 모든 데이터를 저장하는 경우, 당신이 또는 부분적으로 모든 데이터를 다시 작성하지 않고도 업데이트 할 수 없습니다 쿼리에있는 하나의 단위는 기본적입니다.

    그것은 당신이 쿼리와 데이터를 업데이트 할 방법에 따라 달라집니다. 당신은 하나의 행에 모든 데이터를 저장하는 경우, 당신이 또는 부분적으로 모든 데이터를 다시 작성하지 않고도 업데이트 할 수 없습니다 쿼리에있는 하나의 단위는 기본적입니다.

    당신이 행으로 각 요소를 저장하려면, 먼저 MySQL은 계층 적 데이터 관리 읽어야합니다 (MySQL의 특정을하지만 조언은 너무 많은 다른 데이터베이스에 보유).

    당신은 오직 전체 트리를 액세스하는 경우, 인접리스트 모델은 어려운 재귀 쿼리를 사용하지 않고 루트 아래의 모든 노드를 검색 할 수 있습니다. 당신은 링크가 머리에 백업하는 것이 여분의 열을 추가 할 경우에 당신은 * WHERE head_id = @id을 선택을하고 하나의 비 재귀 쿼리에서 전체 트리를 얻을 수 있지만 데이터베이스를 denormalizes 수 있습니다.

    일부 데이터베이스는 예를 들어 오라클은 CONNECT BY를 가지고, 저장하고 쉽게 계층 적 데이터를 검색 만든다 사용자 지정 확장이있다.

  6. ==============================

    6.이것은 구글 검색에서 "SQL 나무"를 묻는 상단의 대답은, 나는 오늘 (12 월 2018 년)의 관점에서이 문제를 업데이트하려고합니다.

    이것은 구글 검색에서 "SQL 나무"를 묻는 상단의 대답은, 나는 오늘 (12 월 2018 년)의 관점에서이 문제를 업데이트하려고합니다.

    대부분의 답변은 인접리스트를 사용하여 모두 단순하고 느린 따라서 다른 방법을 권장 것을 의미한다.

    버전 8 이후 (게시 2018년 4월) MySQL을 지원하는 공통 테이블 표현식 (CTE)를 재귀. MySQL은 조금 늦게 쇼 그러나 이것은 새로운 옵션을 엽니 다.

    인접성 목록을 관리 할 수있는 재귀 쿼리를 사용하는 방법에 대해 설명합니다 여기에 튜토리얼이있다.

    재귀 이제 데이터베이스 엔진 내에서 완전하게 실행, 그것은 (이 스크립트 엔진에서 실행했을 때) 방식으로 훨씬 더 빨리 과거보다.

    여기 블로그는 일부 성능 제공 (모두 바이어스하는 대신 MySQL을 포스트 그레스에 대한)하지만 그럼에도 불구하고 그 인접리스트가 느린 될 필요가 없습니다 보여줍니다.

    내 결론 그래서 오늘은 :

  7. ==============================

    7.각 노드 행 (일반 노드 데이터에 추가) 부모 ID를 포함 표 "노드"와 같은 뭔가. 루트의 경우, 부모는 NULL이다.

    각 노드 행 (일반 노드 데이터에 추가) 부모 ID를 포함 표 "노드"와 같은 뭔가. 루트의 경우, 부모는 NULL이다.

    물론, 아이들을 찾는이 브랜드는이 소모 더 많은 시간을 비트하지만,이 방법은 실제 데이터베이스은 매우 간단합니다.

  8. ==============================

    8.가장 좋은 방법은, 내가 실제로 각 노드를 부모 ID가 부모 노드의 ID입니다 ID와 PARENT_ID를 제공하는 것입니다 생각합니다. 이 혜택의 몇 가지를 가지고

    가장 좋은 방법은, 내가 실제로 각 노드를 부모 ID가 부모 노드의 ID입니다 ID와 PARENT_ID를 제공하는 것입니다 생각합니다. 이 혜택의 몇 가지를 가지고

  9. from https://stackoverflow.com/questions/2175882/how-to-represent-a-data-tree-in-sql by cc-by-sa and MIT license