식별 관계는 논리적으로는 "부모 없이는 자식이 없다"는 규칙을 잘 표현하는 것처럼 보인다. 하지만 실제 서비스 개발·운영 관점에서 보면 여러 가지 심각한 단점이 드러난다.
1번 게시글의 2번 댓글 (board_id=1, comment_no=2)을 2번 게시글로 옮겨야 하는 상황을 생각해 본다.
-- comment_id = 2번 댓글을 2번 게시글로 옮긴다.
UPDATE comment_non_identifying
SET board_id = 2
WHERE comment_id = 2;
comment_id=2는 그대로 유지된다.board_id만 변경하면 된다.(board_id, comment_no)이므로, board_id를 1에서 2로 바꾸는 순간 PK 자체가 바뀐다.즉, 식별 관계는 부모와 자식을 강하게 결합(Tight Coupling) 시키기 때문에, 관계 변경에 극도로 약한 구조가 된다.
게시글–댓글–대댓글(BOARD–COMMENT–REPLY)를 모두 식별 관계로 설계하면 다음과 같은 구조가 된다.
CREATE TABLE board_identifying (
board_id BIGINT NOT NULL AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
PRIMARY KEY (board_id)
);
CREATE TABLE comment_identifying (
board_id BIGINT NOT NULL,
comment_no BIGINT NOT NULL,
content TEXT NOT NULL,
PRIMARY KEY (board_id, comment_no),
CONSTRAINT fk_comment_to_board
FOREIGN KEY (board_id)
REFERENCES board_identifying (board_id)
);
CREATE TABLE reply_identifying (
board_id BIGINT NOT NULL,
comment_no BIGINT NOT NULL,
reply_no BIGINT NOT NULL,
content TEXT NOT NULL,
PRIMARY KEY (board_id, comment_no, reply_no),
CONSTRAINT fk_reply_to_comment
FOREIGN KEY (board_id, comment_no)
REFERENCES comment_identifying (board_id, comment_no)
);
board_id → board_id, comment_no → board_id, comment_no, reply_no로 PK가 계속 비대해진다.SELECT *
FROM reply_identifying
WHERE board_id = 1
AND comment_no = 10
AND reply_no = 3;