멤버 정보가 있고 프로필 정보가 있다.
이걸 분리하는 게 좋을까?
우선, 현재 로직은 회원가입을 하고서 추가로 프로필을 등록하는 방식이다.
참고: The best way to use one-to-one table relationships
이 글을 보고 사용 용도를 확인했다.
1)프로필이 필수가 아니고 Optional일 경우
프로필에 들어가는 칼럼들이 꼭 필요한 게 아니고, 선택사항이라면 굳이 멤버에 null값으로 갖고 있는 대신 저렇게 별도의 테이블로 뺄 수 있다. 그러면, 이때 프로필에 들어가는 값에 not null 설정을 추가할 수 있게 된다.
만약에, 프로필에 들어가야 할 '대표 성향'과 '세부성향'이 둘다 꼭 필요한데 대표 성향만 들어갔다고 해보자. 이런 문제가 발생하지 않게끔 로직을 복잡하게 할 바엔 저렇게 테이블을 별도로 뺼 수 있다.
프로필에 있는 정보는 다 필요하다. 근데 not null 설정을 걸지 못해서 그 중에 하나의 값이 안 들어갈 위험도 있는 것으로 보인다.
2) 낙관적 락과 관련된 이슈
포스트와 유저의 관계로 생각을 해보자.
하나의 포스트를 여러 유저가 동시에 변경하려고 하는데, 각각 다른 칼럼들을 수정한다.
version(낙관적 락에 쓰는 칼럼)이 하나라면 첫번째 유저가 값을 변경하면 나머지 유저들의 변경값을 낙관적 락 예외가 터진다. 각각 다른 칼럼을 변경하는 것이이게 예외가 발생하면 안 되는 상황인데도 예외가 터지는 것.
이 경우에는 세가지 상황으로 분리할 수 있다.
이 상황은 사실 지금 케이스와는 크게 관련이 있는 것은 아니지만 정리 차원에서 기록해둔다.
3)비관적 락 관련
하나의 트랜잭션이 레코드를 수정하면, 그 레코드는 락에 걸린다.
그래서, 여러 사람이 동시에 하나의 레코드를 수정하려고 하면 계속 락을 받을 때까지 기다려야 한다. 테이블을 분리하면 이런 일이 발생하지 않는다.
이 부분도 지금 상황과는 크게 관련이 없다.
만약에 나중에 다른 유저로부터 받은 좋아요 수같은 것들을 따로 칼럼으로 넣어둔다면 관련이 있긴 하다.
4)버퍼 풀
관계형 디비는 테이블과 인덱스 페이지를 버퍼 풀에 캐시해둔다. 다음번에 동일한 페이지를 로드할 때, 이를 활용하려고 하는 것이다.
테이블이나 인덱스를 변견하면, 버퍼풀에 있는 페이지가 언젠가(체크포인트에서) 디스크로 플러시된다.
테이블에 여러개의 칼럼이 있다면, 칼럼이 변경될 떄마다 더티 페이지를 만들고 전체 페이지가 다시 디스크로 플러시 돼야 한다.
99%의 칼럼은 절대 변경이 안되는데 나머지 칼럼이 변경되느라 계속 플러시돼야 하는 것. 플러시 작업 자체가 비용이 들기 때문에 비효율적이라는 것이다.
자주 변경되는 것과 그렇지 않은 것의 테이블을 분리하면 해결되는 문제다.
참고: Relational Database Design: One-to-One Relationships and When to Use Them
사람이라는 테이블이 있다고 해보자. 어떤 사람은 죽고, 어떤 사람은 살아 있다.
그렇다면, 특정 사람이 죽었다는 것을 표시하려면 별도의 테이블을 만들어서 OneToOne으로 만들 수 있다.
또 다른 예로는 병원의 직원들을 생각해보자. 일반 직원 말고, 의사와 간호사만이 갖는 특정 칼럼이 있다. 그러면, 별도의 테이블로 분리하는 게 효율적이다.
만약 병원이 일반 직원들의 정보보다 의사와 간호사의 특정 칼럼에 더 많이 접근한다면? 테이블로 분리하는 게 더 효율적이다. db는 often-accessed “pages” of data를 캐시에 넣어둘 것이다.
원투원 관계로 설계의 유연성도 얻을 수 있다. 직원 테이블이 있고, 직원들의 sns 정보를 테이블로 분리했다고 해보자. 이 테이블을 변경하는거나 지우는 게 더 유연해질 수 있다. (기존 애플리케이션의 db 테이블에 영향을 주지 않으면서 새로운 기능을 추가할 수 있다.)
데이터베이스에서 특정 데이터를 읽어올 때, 엔진은 일반적으로 필요한 열만 메모리에 로드하는 것이 아니라, 전체 행을 메모리에 로드하는 경우가 많다.
행에 포함된 필드(열)가 적을수록 행이 차지하는 공간이 줄어들어, 하나의 메모리 페이지에 더 많은 행을 담을 수 있다. 하나의 페이지에 더 많은 행이 들어가면 디스크 접근 횟수가 줄어들어 성능이 개선될 수 있다.
현재 단계에서는 유저가 가입을 하고서, 프로필을 등록을 안할 수도 있다.
그렇다면, User 테이블에 칼럼들을 모두 넣어놓으면 not null 설정을 할 수가 없게 된다.
그러니 일단 테이블을 분리하는 걸로 결정했다.