Closed mikonu closed 1 month ago
안녕하세요. 궁금증이 생겨서 코멘트 남겨놓습니다. VARCHAR값을 Primary Key로 등록해서 발생하는 성능 저하가 궁금해서 코멘트 남겨놓습니다. Mysql InnoDB의 경우 Primary Key를 클러스터링 인덱스 방식으로 데이터를 저장합니다.
물론 현재 JPA에서 제공하는 매서드를 편하게 사용할 수 있다는 장점은 매우 크다고 생각합니다.
@hegunhee 좋은 질문입니다. 새 pk가 bigint
-> varchar
로 바뀔 경우 어떤 성능 저하가 있을지 예상하려면 1. 우선 두 자료형이 클러스터링 인덱스로 지정되었을 경우 특별한 퍼포먼스 차이가 있는지 확인해야 하고 2. 데이터 사이즈가 문제라면 두 자료형의 데이터 사이즈 차이가 얼마나 될지를 판단하면 좋겠죠.
이런 측면에서 userId
의 varchar 길이를 최대 몇 자와 같이 지정해주면 퍼포먼스 저하를 최소화해줄 수 있겠죠. 그럼에도 불구하고 본질적인 퍼포먼스 차이가 있다면 다음과 같은 점들을 고려해보면 좋을 겁니다:
userId
를 pk로 잡을 경우 예상되는 클러스터링 인덱스 사이즈 증가치는 몇 퍼센트인가?
bigint
사이즈는 8 bytes
varchar
평균 사이즈를 중간값으로 한다고 했을 때 줄 수 있는 최대 길이는 8 * 2 - 1 = 15자
-> 길이 15를 주면 얼추 사이즈 변화가 크지 않겠다고 예상할 수 있음 (사실은 이것보다 짧게 줘야 함)varchar
사이즈 30자를 허용하면 대략 자료형 변화로 인한 데이터 사이즈가 2배 이상이 될 것으로 짐작할 수 있음id
를 pk로 유지할경우, id
는 메타정보이므로 서비스에 노출시키지 않을 전망이다. 유저를 특정하려면 userId
를 쓰게 될 거고, 결국 여기에 secondary index가 적용된다.
userId
를 clustering index 운용하기 vs. 쓰지 않는 id
를 pk로 놔두고 userId
를 secondary index로 운용하기userId
를 secondary index로 운용하는 경우라도, pk index가 여전히 존재한다는 점도 생각해야 한다.userId
가 pk가 아니라면 별도로 해당 키를 where절 검색하는 쿼리 메소드를 작성해줘야 하고, 엔티티 참조만을 가져오는 lazy loading의 이점을 간단하게 활용할 수도 없다.이 점을 모두 고려하면, userId
를 pk로 설정하여 보는 손해가 어느 정도인지를 좀 더 명확하게 가늠할 수 있게될 겁니다.
저는, 결론부터 말하면 성능 저하 부작용이 우려할 수준에 이르지 않는다고 생각합니다.
+강의라는 특수한 상황이라 id
pk를 쓰지 않는 상황을 직접 실습하는 기회를 주는 목적도 있음을 기억하세요.
db 성능과 개발자의 편의성 중 어디를 선택해야 하는가? 는 당연히 둘 다 중요한 가치이기 때문에 일괄적으로 판단할 수 없습니다. 관례도 살펴보고, 우리 서비스의 특성과 상황을 중심으로 고려해야 합니다. 당연히 작업하기 전에 논의를 거치는 것이 좋겠죠. 그래서 최선의 답을 선택하고 진행하도록 합니다.
https://github.com/mikonu/fastcampus-project-board/blob/1da46305c2d8091609eab6b07e69f0ff17aa8ce6/src/main/java/com/fastcampus/projectboard/domain/UserAccount.java#L18-L25
현재 회원 계정 엔티티는 PK로
id
를 자동 채번(auto_increment
)하여 쓰고 있다. 그런데 이id
운용 방식은 큰 의미가 없어 보인다. 회원 정보는 유저가 가입하면서 입력할 ID(userId
)로 고유하게 특정되므로, 별다른 부작용이 없다면userId
를 PK로 쓰는 것도 효율적일 것 같다. 특히userId
를 PK로 쓰면,userId
를 이용한 참조 쿼리 메소드를 편리하게 사용할 수 있는 이점이 생긴다. 이를 설계에 반영해보자.Reference
23