PostgreSQL에서 ltree를 사용하여 계층 구조 데이터를 처리하는 방법
10874 단어 PostgreSQLltree계층 구조 데이터
무엇이 ltree입니까?
Ltree는 PostgreSQL 모듈입니다.이것은 층수 구조에 저장된 데이터의 라벨을 나타내는 데이터 형식ltree를 실현했다.태그 트리 검색을 위한 광범위한 도구가 제공됩니다.
왜 ltree를 선택했습니까?
초기 데이터
우선, 데이터베이스에서 확장을 활성화해야 합니다.다음 명령을 사용하여 이 작업을 수행할 수 있습니다.
CREATE EXTENSION ltree;
테이블을 만들고 데이터를 추가합니다.
CREATE TABLE comments (user_id integer, description text, path ltree);
INSERT INTO comments (user_id, description, path) VALUES ( 1, md5(random()::text), '0001');
INSERT INTO comments (user_id, description, path) VALUES ( 2, md5(random()::text), '0001.0001.0001');
INSERT INTO comments (user_id, description, path) VALUES ( 2, md5(random()::text), '0001.0001.0001.0001');
INSERT INTO comments (user_id, description, path) VALUES ( 1, md5(random()::text), '0001.0001.0001.0002');
INSERT INTO comments (user_id, description, path) VALUES ( 5, md5(random()::text), '0001.0001.0001.0003');
INSERT INTO comments (user_id, description, path) VALUES ( 6, md5(random()::text), '0001.0002');
INSERT INTO comments (user_id, description, path) VALUES ( 6, md5(random()::text), '0001.0002.0001');
INSERT INTO comments (user_id, description, path) VALUES ( 6, md5(random()::text), '0001.0003');
INSERT INTO comments (user_id, description, path) VALUES ( 8, md5(random()::text), '0001.0003.0001');
INSERT INTO comments (user_id, description, path) VALUES ( 9, md5(random()::text), '0001.0003.0002');
INSERT INTO comments (user_id, description, path) VALUES ( 11, md5(random()::text), '0001.0003.0002.0001');
INSERT INTO comments (user_id, description, path) VALUES ( 2, md5(random()::text), '0001.0003.0002.0002');
INSERT INTO comments (user_id, description, path) VALUES ( 5, md5(random()::text), '0001.0003.0002.0003');
INSERT INTO comments (user_id, description, path) VALUES ( 7, md5(random()::text), '0001.0003.0002.0002.0001');
INSERT INTO comments (user_id, description, path) VALUES ( 20, md5(random()::text), '0001.0003.0002.0002.0002');
INSERT INTO comments (user_id, description, path) VALUES ( 31, md5(random()::text), '0001.0003.0002.0002.0003');
INSERT INTO comments (user_id, description, path) VALUES ( 22, md5(random()::text), '0001.0003.0002.0002.0004');
INSERT INTO comments (user_id, description, path) VALUES ( 34, md5(random()::text), '0001.0003.0002.0002.0005');
INSERT INTO comments (user_id, description, path) VALUES ( 22, md5(random()::text), '0001.0003.0002.0002.0006');
또한 색인을 추가해야 합니다.
CREATE INDEX path_gist_comments_idx ON comments USING GIST(path);
CREATE INDEX path_comments_idx ON comments USING btree(path);
보시다시피,comments표를 만들 때path 필드가 있습니다. 이 필드는 이 테이블의tree 모든 경로를 포함합니다.보시다시피 트리 구분자에 대해서는 4개의 숫자와 점을 사용합니다.commenets 테이블에서 path가'0001.0003'의 기록을 찾습니다.
$ SELECT user_id, path FROM comments WHERE path <@ '0001.0003';
user_id | path
---------+--------------------------
6 | 0001.0003
8 | 0001.0003.0001
9 | 0001.0003.0002
11 | 0001.0003.0002.0001
2 | 0001.0003.0002.0002
5 | 0001.0003.0002.0003
7 | 0001.0003.0002.0002.0001
20 | 0001.0003.0002.0002.0002
31 | 0001.0003.0002.0002.0003
22 | 0001.0003.0002.0002.0004
34 | 0001.0003.0002.0002.0005
22 | 0001.0003.0002.0002.0006
(12 rows)
EXPLAIN 명령을 통해 이 SQL을 확인하겠습니다.
$ EXPLAIN ANALYZE SELECT user_id, path FROM comments WHERE path <@ '0001.0003';
QUERY PLAN
----------------------------------------------------------------------------------------------------
Seq Scan on comments (cost=0.00..1.24 rows=2 width=38) (actual time=0.013..0.017 rows=12 loops=1)
Filter: (path <@ '0001.0003'::ltree)
Rows Removed by Filter: 7
Total runtime: 0.038 ms
(4 rows)
테스트를 위해 seq scan을 비활성화합니다.
$ SET enable_seqscan=false;
SET
$ EXPLAIN ANALYZE SELECT user_id, path FROM comments WHERE path <@ '0001.0003';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------
Index Scan using path_gist_comments_idx on comments (cost=0.00..8.29 rows=2 width=38) (actual time=0.023..0.034 rows=12 loops=1)
Index Cond: (path <@ '0001.0003'::ltree)
Total runtime: 0.076 ms
(3 rows)
현재 SQL은 느리지만 SQL이 index를 어떻게 사용하는지 볼 수 있습니다.첫 번째 SQL 문장은 테이블에 데이터가 많지 않기 때문에 sequence scan을 사용합니다.
우리는 select'path<@'0001.0003'를 실현 방법으로 바꿀 수 있다.
$ SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*';
user_id | path
---------+--------------------------
6 | 0001.0003
8 | 0001.0003.0001
9 | 0001.0003.0002
11 | 0001.0003.0002.0001
2 | 0001.0003.0002.0002
5 | 0001.0003.0002.0003
7 | 0001.0003.0002.0002.0001
20 | 0001.0003.0002.0002.0002
31 | 0001.0003.0002.0002.0003
22 | 0001.0003.0002.0002.0004
34 | 0001.0003.0002.0002.0005
22 | 0001.0003.0002.0002.0006
(12 rows)
당신은 데이터의 순서를 잊어서는 안 됩니다. 다음과 같은 예입니다.
$ INSERT INTO comments (user_id, description, path) VALUES ( 9, md5(random()::text), '0001.0003.0001.0001');
$ INSERT INTO comments (user_id, description, path) VALUES ( 9, md5(random()::text), '0001.0003.0001.0002');
$ INSERT INTO comments (user_id, description, path) VALUES ( 9, md5(random()::text), '0001.0003.0001.0003');
$ SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*';
user_id | path
---------+--------------------------
6 | 0001.0003
8 | 0001.0003.0001
9 | 0001.0003.0002
11 | 0001.0003.0002.0001
2 | 0001.0003.0002.0002
5 | 0001.0003.0002.0003
7 | 0001.0003.0002.0002.0001
20 | 0001.0003.0002.0002.0002
31 | 0001.0003.0002.0002.0003
22 | 0001.0003.0002.0002.0004
34 | 0001.0003.0002.0002.0005
22 | 0001.0003.0002.0002.0006
9 | 0001.0003.0001.0001
9 | 0001.0003.0001.0002
9 | 0001.0003.0001.0003
(15 rows)
이제 정렬:
$ SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*' ORDER by path;
user_id | path
---------+--------------------------
6 | 0001.0003
8 | 0001.0003.0001
9 | 0001.0003.0001.0001
9 | 0001.0003.0001.0002
9 | 0001.0003.0001.0003
9 | 0001.0003.0002
11 | 0001.0003.0002.0001
2 | 0001.0003.0002.0002
7 | 0001.0003.0002.0002.0001
20 | 0001.0003.0002.0002.0002
31 | 0001.0003.0002.0002.0003
22 | 0001.0003.0002.0002.0004
34 | 0001.0003.0002.0002.0005
22 | 0001.0003.0002.0002.0006
5 | 0001.0003.0002.0003
(15 rows)
lquery의 비별표 탭 끝에 수식자를 몇 개 추가하여 완전히 일치하는 것보다 더 일치하게 할 수 있습니다."@"- 대소문자 일치를 구분하지 않습니다. 예를 들어 a @ 일치 A
"*"- 접두사가 있는 모든 태그와 일치합니다. 예를 들어 foo*와 일치합니다.
"%"- 밑줄로 시작하는 단어와 일치
$ SELECT user_id, path FROM comments WHERE path ~ '0001.*{1,2}.0001|0002.*' ORDER by path;
user_id | path
---------+--------------------------
2 | 0001.0001.0001
2 | 0001.0001.0001.0001
1 | 0001.0001.0001.0002
5 | 0001.0001.0001.0003
6 | 0001.0002.0001
8 | 0001.0003.0001
9 | 0001.0003.0001.0001
9 | 0001.0003.0001.0002
9 | 0001.0003.0001.0003
9 | 0001.0003.0002
11 | 0001.0003.0002.0001
2 | 0001.0003.0002.0002
7 | 0001.0003.0002.0002.0001
20 | 0001.0003.0002.0002.0002
31 | 0001.0003.0002.0002.0003
22 | 0001.0003.0002.0002.0004
34 | 0001.0003.0002.0002.0005
22 | 0001.0003.0002.0002.0006
5 | 0001.0003.0002.0003
(19 rows)
parent'0001.0003'를 위해 모든 직접적인 childrens를 찾으러 왔습니다. 다음을 보십시오.
$ SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*{1}' ORDER by path;
user_id | path
---------+----------------
8 | 0001.0003.0001
9 | 0001.0003.0002
(2 rows)
parent'0001.0003'의 모든 childrens를 찾으려면 다음을 보십시오.
$ SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*' ORDER by path;
user_id | path
---------+--------------------------
6 | 0001.0003
8 | 0001.0003.0001
9 | 0001.0003.0001.0001
9 | 0001.0003.0001.0002
9 | 0001.0003.0001.0003
9 | 0001.0003.0002
11 | 0001.0003.0002.0001
2 | 0001.0003.0002.0002
7 | 0001.0003.0002.0002.0001
20 | 0001.0003.0002.0002.0002
31 | 0001.0003.0002.0002.0003
22 | 0001.0003.0002.0002.0004
34 | 0001.0003.0002.0002.0005
22 | 0001.0003.0002.0002.0006
5 | 0001.0003.0002.0003
(15 rows)
children'0001.0003.0002.0002.0002.0005'를 위해 parent를 찾습니다:
$ SELECT user_id, path FROM comments WHERE path = subpath('0001.0003.0002.0002.0005', 0, -1) ORDER by path;
user_id | path
---------+---------------------
2 | 0001.0003.0002.0002
(1 row)
만약 당신의 경로가 유일한 것이 아니라면, 당신은 여러 개의 기록을 얻을 수 있을 것이다.개요
ltree를 사용하는 물화 경로가 매우 간단하다는 것을 알 수 있다.본문에서 나는 ltree의 모든 가능한 용법을 열거하지 않았다.이것은 전체 텍스트 검색 문제ltxtquery로 간주되지 않습니다.하지만 PostgreSQL 공식 문서 http://www.postgresql.org/docs/current/static/ltree.html 에서 찾을 수 있습니다.
더 많은 PostgreSQL 핫이슈, 뉴스 동향, 하이라이트 이벤트에 대해 알고 싶으시면 중국 PostgreSQL 공식 사이트를 방문하십시오: www.postgresqlchina.com
더 많은 PostgreSQL 관련 지식, 기술, 업무 문제를 해결하려면 중국 PostgreSQL 공식 퀴즈 커뮤니티를 방문하십시오: www.pgfans.cn
더 많은 PostgreSQL 관련 자료, 도구, 플러그인 문제를 다운로드하려면 중국 PostgreSQL 공식 다운로드 사이트를 방문하십시오: www.postgreshub.cn
PostgreSQL에서 ltree를 사용하여 차원 구조 데이터를 처리하는 것에 관한 이 글은 여기에 소개되었습니다. 더 많은 PostgreSQL 차원 구조 데이터와 관련된 내용은 저희 이전의 글을 검색하거나 아래의 관련 글을 계속 훑어보십시오. 앞으로 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Redmine 데이터베이스를 MySQL에서 PostgreSQL로 마이그레이션 (보충)Redmine 의 Database 를 MySQL 로 운용하고 있었습니다만, MySQL 5.6 이상이나 MariaDB 에는 , , 이러한 티켓이 수년 동안 방치된 상황을 감안하여, PostgreSQL로 마이그레이션하기...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.