Database/SQL

MySQL - 비트마스크 컬럼을 사용하지 않아도 되는 이유 (+ SET Type)

JaeHoney 2022. 6. 30. 08:54

MySQL에서 동일한 여러가지 플래그를 만들 일이 생긴다.

 

다음 그림은 내가 신입때 만든 프로젝트의 ERD 일부이다.

해당 테이블을 설계하면서 고려했던 방식은 두 가지이다.

  • 비트마스크로 부모 테이블안에 1개 컬럼으로 저장하는 방식
  • 테이블 1개로 추출해서 저장하는 방식

비트마스크로 처리하면 가독성을 망치고 구현이 힘들어진다. 그리고 DBMS에서 컬럼마다 데이터 크기를 정의할 수 있다. 그래서 두 번째 방식으로 테이블을 설계하게 되었다.

 

(발표 때 아무도 태클 걸어 주지 않으셨다.)

SET TYPE

MySQL 데이터 타입 레퍼런스를 보던 중 SET이라는 것이 눈에 들어왔다.

 

SET은 ENUM처럼 문자열 값을 MySQL 내부적으로 정수 값으로 매핑해서 저장하는 방식의 타입이다. 하지만 SET은 ENUM과 달리 하나의 컬럼에 1개 이상의 값을 저장할 수 있다.

 

MySQL 서버는 SET을 내부적으로 여러 곳에 데이터가 저장되는 것이 아니라 BIT-OR 연산을 거쳐 한 곳에 데이터를 저장한다.

  • SET 타입의 멤버 수가 8개 이하라면 1바이트를 사용한다.
  • SET 타입의 멤버 수가 9~16개라면 2바이트를 사용한다
  • ...

다음의 예제를 살펴보자.

CREATE TABLE tb_set (
    fd_set SET('TENNIS', 'SOCCER', 'GOLF', 'BASKETBALL', 'BILLIARD')
);

INSERT INTO tb_set (fd_set) VALUES ('SOCCER'), ('GOLF, TENNIS');

INSERT 문에서 두 개의 레코드를 삽입했다.

 

이 중 'GOLF'를 포함하는 레코드를 찾을 경우 FIND_IN_SET을 사용하면 된다.

SELECT * FROM tb_set WHERE FIND_IN_SET('GOLF', fd_set);

MySQL의 SET Type은 Java의 Set Type과 쉽게 매핑할 수 있어서 구현을 풀어내기도 쉽다는 장점이 있다.

 

반면, ENUM과 마찬가지로 SET 중간에 새로운 아이템을 추가하는 경우 테이블의 읽기 잠금과 리빌드 작업이 필요하기 때문에 신중하게 결정해야 한다.