일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Linked list
- DFS
- django
- hash table
- Algorithm
- gpdb
- boj
- BFS
- GitHub
- programmers
- 알고리듬
- 코딩테스트
- 코테
- CSV
- Trie
- Priority Queue
- SQL
- spring boot
- JavaScript
- Vue.js
- SWEA
- Bruth Force
- Data Structure
- 모의SW역량테스트
- aws
- 구현
- 알고리즘
- Python
- 시뮬레이션
- Back tracking
- Today
- Total
hotamul의 개발 이야기
대댓글 기능 데이터 모델링 #1 (Adjacency List) 본문
사용자들이 댓글을 달고 서로에게 대답하면서 토론 스레드를 만들 수 있는 서비스를 개발할 때 각 댓글들이 어떤 댓글의 답변인지 알 수 있도록 아래와 같이 parent_id를 이용해서 간단하게 Comments 테이블을 구성할 수 있다.
CREATE TABLE Comments (
comment_id SERIAL PRIMARY KEY,
parent_id BIGINT UNSIGNED,
comment TEXT NOT NULL,
FOREIGN KEY (parent_id) REFERENCES Comments(comment_id)
);
그런데 딱 봐도 위와 같은 테이블 구성은 하나의 SQL 쿼리로 모든 댓글 연결들을 조회하는 것이 어려워 보인다.
바로 자식 댓글까지는 쉽게 얻을 수 있지만, 댓글 스레드는 무한히 생성될 수 있기 때문에 한 스레드의 모든 댓글을 조회하려면 아래와 같이 여러 번의 SQL 쿼리를 실행해야 한다.
SELECT c1.*, c2.*, c3.*, c4.*
FROM Comments c1 -- 1st level
LEFT OUTER JOIN Comments c2
ON c2.parent_id = c1.comment_id -- 2nd level
LEFT OUTER JOIN Comments c3
ON c3.parent_id = c2.comment_id -- 3rd level
LEFT OUTER JOIN Comments c4
ON c4.parent_id = c3.comment_id; -- 4th level
위 쿼리는 점점 더 깊은 수준의 comment를 column에 추가하고 있는데 이는 매우 비효율적이고 어색해 보인다. 그리고 COUNT()와 같은 aggregate 연산 또한 어려워 보인다.
여러 번의 SQL 쿼리를 실행하거나 연속적인 LEFT OUTER JOIN을 이용하는 것 대신에, 모든 댓글을 한 번에 조회해서 메모리 로드하고 트리 형태로 다시 조립/정렬하는 방법도 있다. 하지만 댓글이 수백 수천 개씩 생성된다면 메모리에 모든 댓글을 조회해서 조립/정렬하는 것은 쉽지 않을 것이다.
그러면 위 방법이 무조건적으로 틀린 것이냐? 그것은 아니다.
Adjacency Lists 설계는 종종 사용되고 어떠한 경우에는 적절한 방법일 수 있다. Adjacency Lists 설계의 장점은 주어진 노드의 부모, 자식 노드를 직접 검색할 수 있다는 것이다. 그리고 쉽게 레코드를 삽입할 수 있다.
일부 RDBMS에서는 Adjacency Lists 형식으로 저장된 정보를 쉽게 다루기 위해 WITH
키워드를 이용한 Common Table Expression(공통 테이블 표현식)를 지원한다.
WITH CommentTree
(comment_id, post_id, parent_id, author, comment, depth)
AS (
SELECT *, 0 AS depth FROM Comments
WHERE parent_id IS NULL
UNION ALL
SELECT c.*, ct.depth+1 AS depth FROM CommentTree ct
JOIN Comments c ON (ct.comment_id = c.parent_id)
)
SELECT * FROM CommentTree WHERE post_id = 1234;
Microsoft SQL Server 2005, Oracle 11g, IBM DB2, PostgreSQL 8.4에서는 위처럼 CTE을 사용하여 재귀적인 쿼리를 작성할 수 있다. MySQL, SQLite,... 는 아직 이러한 문법을 지원하지 않지만 Adjacency Lists를 사용하는 것이 RDBMS 브랜드에 따라 그렇게까지 제한적으로 보이지는 않는다.
그럼에도 댓글 스레드를 다루는 더 효율적인 방법이 뭐가 있을까?
- Path Enumeration
- Nested Sets (작성 중...)
- Closure Tables (작성 중...)
'Dev. > DB' 카테고리의 다른 글
대댓글 기능 데이터 모델링 #2 (Path Enumeration) (0) | 2024.01.03 |
---|---|
[CS - DB] Isolation level of Transactions (0) | 2022.12.15 |