질문 다시 정리함.
쇼핑몰에 상품-주문 테이블 설계중인데, 어떤 방식이 최선임?
A. 방법1
item 테이블에 모든 상품을 다 넣기 보다는, phone 테이블, cloth 테이블, furniture 테이블 등으로 쪼개어 반 정규화 한 방식.
장점
1. 개별 제품 상세 페이지 쿼리는 빠름
단점
1. 구매자가 주문목록 query하려면, 모든 상품 테이블들 다 돌면서 product_id 찾아야 하니까 엄청 느림.
이걸 완화하기 위해, 모든 상품테이블에 들어았는 product_id를 인덱스 거는게 최선일지 모르겠음.
2. 또한, 상품 카테고리별로 테이블 만들어줘야 해서 테이블 갯수가 수십~수백개로 늘어남.
B. 방법2
item 테이블 마저 없애고, order_item테이블에 모든 상품 테이블들의 pk를 fk로 받는 방식
장점
1. 개발 상품 페이지 쿼리는 빠르다.
2. 방법1에서 item테이블의 pk를 가지고, 수십~수백개의 상품 테이블들 돌면서 fk 찾기 안해도 됨.
단점
a. 주문목록 query하려면,
1. null check 먼저 하고,
2. 해당 아이템의 fk 가지고 아이템 찾는 식일텐데,
테이블에 null값 들어가는게 마음에 안듬.
뭔가 null 처리 잘못되면 서버 터질거 같고,
null checking 하려고 서비스단에 exception handling 해야할 것 같음.
(코드상 깔끔하지 못함)
b. 또한, 상품 종류가 100가지라 상품 테이블이 100가지면, order_item가 받는 상품들의 fk가 100개+가 될텐데, 필드값이 100개인 테이블 개오버인 것 같다.
방법3. 정규화를 한 케이스.
모든 상품 카테고리마다, 옵션이 다르니까(ex. 핸드폰들이 공유하는 옵션과 생선이나 가구, 옷 등이 공유하는 옵션이 다름), 옵션을 테이블로 정규화 해놓음.
장점
1. 정규화가 잘 되있어서 아름다움. 기부니가 좋음.
2. 나중에 데이터 가지고 가지고 놀든, 다른곳으로 머지를 하든 할 때, 정해진 형식, 규격화로 저장되어 있기 때문에, 편함.
단점
1. 개발 상품 페이지 쿼리할 떄 subquery & join 겁나 많이 해야 해서 느림.
2. 주문목록 query할 때도 join 8 subquery 많이 해야 해서 느림.
3. 상품 등록/업데이트/삭제 시, product/product_item/category/option/option_variation/product_option_variation 이 6개 테이블에 트랜잭션/lock 걸릴텐데, 너무 느릴 것 같음.
반정규화는 흔히 일어나는 일이고 글이 너무 길고 중간중간 뭔소린지 모를 말들이 있어서 제대로 읽기가 힘들어
반정규화 흔히 일어나는 일이라는건 캐치했음
내가 봐도 횡설수설한 것 같아서 다시 생각하고 정리했음.
비정규화는 일종의 최적화이고 되돌리기 힘든 과정임, 서비스 초기 단계라면 구현된 기능 자체가 수정&삭제가 빈번한데 이렁 경우 정규화된 구조를 사용하여 기능의 수정&삭제같은 유지보수를 저렴한 비용으로 유연하게 할 수 있도록 하는 것이 맞음 서비스가 더 커진다 해도 캐싱, 인덱싱, 분산처리(가용영역 추가, 비쌈)같은 테크닉을 쓸 수 있고
나중에 서비스가 커져서 비정규화나 MSA같이 RDBMS가 보장해주는 것 일부를 포기하고 더 최적화를 해야할 경우가 오면 이때 해당 프로젝트 진행하면됨(비용 장난아님)
결론: 정규화하고 최적화는 나중에 병목이 생기면
오호~ 그러하군. 이게 말로만 듣던 확장성을 고려한 유연한 설계구나. 설계의 세계는 심오하군. ㄱㅅㄱㅅ 도움 많이 되었음
간단한 쿼리의 조인 속도는 보통 걱정 안함. 조회수 순, 추천제품 순으로 캐싱해버리니까 걱정하던거의 1000배는 빨라짐 확장성이 우선임. 이런 고민 나도 신입 때 했으면 지금쯤 구글 갔는데
아 그렇네 캐싱을 생각을 못했네. 확장성과 일관정 형태 갖추는건 정규화로 하고, 반정규화로 성능 가져갈건 캐싱으로 메꾸는구나~ ㄱㅅㄱㅅ 도움 많이 됨