문제

객체 태그 지정을 위해 MySQL 데이터베이스를 사용하는 PHP 웹 애플리케이션이 있는데, 여기에 대한 답변으로 허용된 태그 구조를 사용했습니다. 이 SO 질문.

각 태그가 고유한 상위 태그를 가질 수 있는 태그 계층 구조를 구현하고 싶습니다.상위 태그 T를 검색하면 T의 모든 하위 항목과 일치합니다(예:T, 부모가 T인 태그(T의 자식), T의 손자 등).

이를 수행하는 가장 쉬운 방법은 태그의 상위 태그 ID가 포함된 태그 테이블에 ParentID 필드를 추가하거나 태그에 상위 태그가 없는 경우 일부 매직 넘버를 추가하는 것입니다.그러나 자손을 검색하려면 각 '세대'에서 태그를 찾기 위해 데이터베이스 전체를 반복적으로 검색해야 하는데, 저는 이를 피하고 싶습니다.

(아마도) 더 빠르지만 덜 정규화된 방법은 각 태그의 모든 하위 항목 또는 각 태그의 모든 하위 항목을 포함하는 테이블을 만드는 것입니다.그러나 이는 데이터베이스의 데이터가 일관되지 않을 위험이 있습니다(예:태그는 둘 이상의 상위 요소의 하위 요소입니다.

데이터를 가능한 한 정규화한 상태로 유지하면서 하위 항목을 빠르게 찾기 위한 쿼리를 만드는 좋은 방법이 있습니까?

도움이 되었습니까?

해결책 2

알리의 답변에는 링크가 있습니다 Joe Celko의 나무와 Smlies for Smarties의 Trees and Hierrarchies, 내 의심을 확인하는 것은 모든 세계에서 최고를 제공하는 간단한 데이터베이스 구조가 없습니다. 내 목적에 가장 적합한 것은이 책에 자세히 설명 된 "빈번한 삽입 트리"인 것 같습니다.이 책은 Ali의 링크의 "중첩 세트 모델"과 같지만 비정규 인덱싱을 사용합니다. 이것은 O (1) 삽입을 허용합니다 (류 풍의 구조화되지 않은 기본 라인 번호), 때때로 인덱스 개편이 필요할 때와 함께.

다른 팁

두 열을 사용하여 구현했습니다. 나는 다른 언어를 위해 국소화해야했기 때문에 태그 이름을 별도의 필드/테이블에 보관해야했기 때문에 여기서 조금 단순화합니다.

  • 꼬리표

예를 들어이 행을보십시오.

tag            path
---            ----
database       database/
mysql          database/mysql/
mysql4         database/mysql/mysql4/
mysql4-1       database/mysql/mysql4-1/
oracle         database/oracle/
sqlserver      database/sqlserver/
sqlserver2005  database/sqlserver/sqlserver2005/
sqlserver2005  database/sqlserver/sqlserver2008/

등.

사용 like 경로 필드의 연산자는 필요한 모든 태그 행을 쉽게 얻을 수 있습니다.

SELECT * FROM tags WHERE path LIKE 'database/%'

계층 구조에서 노드를 움직일 때와 같은 구현 세부 사항이 있습니다. 모든 어린이 등을 변경해야하지만 어렵지는 않습니다.

또한 경로의 길이가 충분히 길어야합니다. 제 경우에는 경로의 태그 이름이 아니라 경로가 너무 길지 않도록 다른 필드를 사용했습니다.

Kimball이 계층 구조 도우미 테이블이라고 부르는 것을 만들 수 있습니다.

계층 구조가 다음과 같다고 가정해 보겠습니다.a -> b | B-> C | c -> d

다음과 같은 테이블에 레코드를 삽입합니다.

ParentID, ChildID, Depth, Highest Flag, Lowest Flag
A, A, 0, Y, N
A, B, 1, N, N
A, C, 2, N, N
A, D, 3, N, Y
B, B, 0, N, N
B, C, 1, N, N
B, D, 2, N, Y
C, C, 0, N, N
C, D, 1, N, Y
D, D, 0. N, Y

내 생각엔 그 말이 맞는 것 같아....어쨌든.요점은 계층 구조를 올바르게 저장하고 적절한 테이블에서 이 테이블을 구축한다는 것입니다.이 테이블은 Banshee와 같은 쿼리를 수행합니다.B 아래의 첫 번째 수준이 모두 무엇인지 알고 싶다고 가정해 보겠습니다.

WHERE parentID = 'B' and Depth = 1

나는 어떤 종류의 배열을 사용하여 어린이 태그를 보관할 것입니다. 이것은 테이블 자체에 합류하는 것보다 훨씬 빠릅니다 (특히 많은 태그가있는 경우). 살펴 보았고 MySQL에 기본 배열 데이터 유형이 있는지 알 수는 없지만 텍스트 열을 사용하고 직렬화 된 배열을 저장하여이를 에뮬레이션 할 수 있습니다. 속도를 높이고 싶다면 해당 열에 텍스트 검색 색인을 넣어 관련된 태그를 찾을 수 있어야합니다.

편집] Ali의 기사를 읽은 후에는 더 많은 사냥을하고 발견했습니다. 이것 Postgres에서 계층 구조를 구현하기위한 많은 접근 방식에 대한 프레젠테이션. 설명 목적으로 여전히 도움이 될 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top