본문 바로가기
프로젝트

[220809] 데이터 모델링 이슈 정리

by eunoo 2022. 8. 10.

데이터 모델링 과정 중 고민이슈들을 정리해보았다.

논리 모델링 중 이슈

ISSUE1. Password_change(비밀번호 변경 이력)를 USER_SECRET의 이력으로 연결지어야하지 않을까?

 

결론 : 보안 상 이유로 USER_SECRET 과 연결지으면 안된다.

USER_SECRET 엔티티는 보안적인 이유로 사용자의 비밀번호를 따로 빼둔 것이다. 관계에만 집중하느라 엔티티의 목적을 까먹었다. 관계만 보았을 때 USER_SECRET과 연결짓는 것이 맞겠지만 USER_SECRET은 보안이 제일 중요한 엔티티이기 때문에 다른 엔티티와의 관계를 최소화시키는 것이 좋다. 

 

ISSUE2. 신고 내역을 select로 count 하게 되면 모든 유저마다 select를 해야한다. 성능 문제 해결하기.

 

팀 회의를 통해 최종적으로 만든 엔티티를 마지막으로 혼자 검토하는 중 신고내역 엔티티에서 문제점을 발견했다.

기능 구현은 다음과 같이 할 예정이었다.

 

[리뷰 신고내역 엔티티]

신고 번호(PK)
리뷰 아이디
from_user_id(누가)
to_user_id(누구를)
신고 시간
신고 사유

1. 피신고자(to_user_id)가 신고 당한 횟수를 select문으로 count한다.

2. 피신고자(to_user_id)가 신고 당한 횟수가 5이상이면 USER의 신고횟수에 +1 한다.

 

문제가 있음을 느꼈지만 잘 와닿지 않아 엑셀로 더미 데이터를 만들어 쿼리문을 직접 짜보았다.

[리뷰 신고내역 엔티티]

신고 번호 reivew_id from_user_id(누가) to_user_id(누구를) 신고시간 신고사유(왜)
1 1 2022-08-01 00:12:35 1
2 1 2022-08-01 01:12:35 1
3 1 2022-08-01 02:12:35 2
4 1 2022-08-01 03:12:35 1

 

쿼리문을 작성해보면..

select count(*)
from (select to_user_id,review_id from 리뷰신고내역 where to_user_id="마")
where to_user_id>5

쿼리문을 직접 작성해보니 문제점이 바로 보였다. 이렇게 되면 유저마다 신고 당한 횟수를 select 처리해야하는데 그러면 말도 안되게 성능이 떨어진다.

그래서 리뷰 엔티티 각각에 신고 횟수 속성을 추가해주었다.

물리모델링 중 이슈

ISSUE3.  데이터 타입을 INT vs VARCHAR?

데이터 타입은 작을수록 디스크나 메모리, CPU 캐시에 더 적은 공간을 사용하기 때문에 더 빠르다. 그래서 데이터 타입은 작을수록 좋다.

USER테이블의 상태 속성 경우, 총 4개의 값(관리자, 활성, 비활성, 정지)을 가진다. 이 4가지 값은 변하지 않고, 숫자만으로 표현할 수 있다. 0-관리자, 1-활성, 2- 비활성, 3-정지 이렇게 말이다. 그래서 USER테이블의 속성은 TINYINT 로 지정해주었다.

USER테이블의 장르 속성 경우 총 27개의 값을 가질 수 있는데, 이도 마찬가지로 INT로 지정해주었다.

하지만 이 경우는 장르 이름과 번호를 매핑하는 테이블이 필요하여 JOIN을 통해 장르 이름을 가지고 와야한다. 이는 불필요한 JOIN이기 때문에 타입을 VARCHAR로 지정하여 바로 장르 이름을 가지고 오도록 하였다.

 

ISSUE4. NOT NULL과 NULL

컬럼을 NOT NULL로 설정하면 NULL값이 들어올 수 없다는 것이다. 즉 insert할 때 값이 없으면 에러가 발생한다. 값이 없다면 규칙을 정하여 빈 문자열, 특정한 문자를 넣어주던지 해야한다.

NULL로 설정하면 NULL값이 들어올 수 있다. NULL로 들어왔을 때 데이터를 처리할 수 있게 default값을 정해줘야한다.

 

ISSUE5. auto increment와 pk

테이블에 pk를 지정해주지 않으면 mysql에서는 auto increment가 컬럼에 자동 추가되어 hidden pk가 된다.

이는 우리가 pk로 접근하는 것이 거의 불가능하다. 따라서 auto increment를 PK로 지정해주는 작업이 꼭 필요하다.

 


<MySQL 최적의 데이터 타입 선택 방법>

- 타입은 작을 수록 좋다.

- 타입은 단순한 게 좋다. (문자보다는 정수가 더 좋음. 날짜와 시간은 문자열 말고 MYSQL 내장 형식에 저장해야 하고, IP주소는 정수를 이용해 저장)

- 가능하면 NULL을 쓰지 말자.

    - NULL을 저장할 의도가 아니라면 컬럼을 NOT NULL로 정의하자.

    - NULL 허용 칼럼은 저장 공간도 더 많이 사용하며 NULL 허용 컬럼을 인덱싱할 땐 항목마다 한 바이트씩 더 들어감.

    - '값이 없음'을 기록하는 테이블이더라도 NULL보단 0, 빈 문자열, 특수 값 등을 사용하는 것이 고려된다.

 

https://nomadlee.com/mysql-%EC%B5%9C%EC%A0%81%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-%EC%84%A0%ED%83%9D-%EB%B0%A9%EB%B2%95/

댓글