[mysql] enum

kihoo_ni·2024년 6월 13일

🌟 enum


📋 특징

  • ENUM 타입은 MySQL에서 사전에 정의된 문자열 값 목록 중 하나를 선택하여 저장할 수 있게 하는 특별한 데이터 타입.
  • Enum 타입은 지정된 값만을 넣을 수 있고 실제 값은 테이블외에 따로 저장되고 테이블에는 1byte을 이용하여 정수형 index로 저장한다. key,value형식으로 저장되고 key값을 테이블에 저장하는 것과 비슷하다 볼 수 있음.
CREATE TABLE shirts
(
    name VARCHAR(40),
    size ENUM ('x-small', 'small', 'medium', 'large', 'x-large')
);
INSERT INTO shirts (size) VALUES (2); -- 인덱스가 1부터 시작함. 따라서 small이 들어감. 
  • 인덱스 할당: 각 ENUM 값은 1부터 시작하는 인덱스를 가짐. 예를 들어, ENUM('Mercury', 'Venus', 'Earth')에서는 'Mercury'가 인덱스 1, 'Venus'는 2, 'Earth'는 3임(순차대로 할당).

  • 정렬: ENUM 값은 인덱스에 따라 정렬됩니다. 즉, ENUM 값의 정의 순서에 따라 정렬됨. 예를 들어, ENUM('b', 'a')는 'b'가 'a'보다 먼저 정렬됨.

  • 빈 문자열 인덱스: 빈 문자열('')은 인덱스 0을 가짐.

  • ENUM 열의 최대 요소 수: 최대 65,535개의 고유한 요소 가질 수 있음.

  • NULL: ENUM 열은 NULL 값을 허용하도록 정의된 경우 NULL을 저장할 수 있음.

  • 잘못된 값: ENUM 목록에 없는 값을 삽입하면 빈 문자열('')로 설정되며, 이는 인덱스 0을 가짐.

  • Strict SQL 모드: strict SQL 모드가 활성화되면 잘못된 ENUM 값을 삽입할 때 오류가 발생함.

  • 지정된 값만 저장: ENUM 타입은 미리 지정한 특정 값들 중 하나만 열(Column)에 저장할 수 있도록 제한함.

    예를 들어, ENUM('red', 'green', 'blue')로 정의된 ENUM 열에는 'red', 'green', 'blue' 중 하나의 값만 저장할 수 있음.

  • 효율적인 저장: 실제 테이블에서는 ENUM 값 자체가 아닌, 값의 인덱스(정수형 숫자)가 저장됨. 이로 인해 저장 공간이 절약됨.

    예를 들어, ENUM('red', 'green', 'blue') 중 'green'이 선택되면 테이블에는 'green' 대신 해당 값의 인덱스(정수형 숫자 2)가 저장됨.

  • 데이터 외부 저장: ENUM 값들의 리스트는 테이블 외부에서 관리되며, 테이블에는 각 값의 인덱스만 저장됨. 이는 일종의 키-값 (Key-Value) 쌍을 사용하는 것과 비슷함.

    예를 들어, 'red'는 1, 'green'은 2, 'blue'는 3으로 매핑됩니다.

  • 1바이트로 인덱스 저장: ENUM 값의 인덱스는 보통 1바이트 크기의 정수형 데이터로 저장되므로 저장 공간을 효율적으로 사용할 수 있음. 만약 ENUM의 값 개수가 256개를 초과하면 더 큰 크기의 저장 공간을 사용할 수 있음.

  • 숫자 인덱스 해석: 숫자가 ENUM 열에 저장되면, 이 숫자는 가능한 값의 인덱스로 해석됨.

    예를 들어, ENUM('small', 'medium', 'large')에 2를 저장하면, 인덱스 2에 해당하는 'medium'이 저장됨.

  • LOAD DATA와의 호환성: 숫자를 문자열로 취급하는 LOAD DATA 명령과는 다르게 작동함.

  • 혼란 방지: 숫자처럼 보이는 문자열을 ENUM 값으로 사용하는 것은 추천되지 않음. 이런 값들은 혼동을 초래할 수 있기 때문임.

    예를 들어 ENUM('0', '1', '2')가 있는 경우, 숫자 2를 저장하면 인덱스 2에 해당하는 '1'이 저장되고, 문자열 '2'를 저장하면 '2'가 저장됨
    . 숫자 3을 저장(숫자 3이 enum value가 아님)하면, 인덱스 3에 해당하는 '2'가 저장됨.

-- 코드 복사
CREATE TABLE t (numbers ENUM('0','1','2'));

INSERT INTO t (numbers) VALUES (2), ('2'), ('3');
SELECT * FROM t;
-- 출력 결과:
+---------+
| numbers |
+---------+
| 1       |
| 2       |
| 2       |
+---------+

⚙️ 출처: https://dev.mysql.com/doc/refman/8.0/en/enum.html#enum-literals
⚙️ 출처: https://velog.io/@viva99/Mysql-Enum


📋 enum 쓰면 안되는 이유

  1. 데이터가 데이터로서 제대로 다뤄지지 않음

    ENUM을 사용하면 사실상 데이터베이스 메타데이터에 데이터를 저장하는 셈. 이렇게 하면 데이터베이스 정규화 원칙을 위반하게 되며, 이는 여러 문제를 야기할 수 있음.
    예를 들어, 숫자 컬럼에 정수만 허용하거나 날짜 컬럼에 NULL을 허용하지 않는 것은 데이터에 제약을 거는 것으로 괜찮지만, ENUM으로 값을 제한하는 것은 데이터로 다뤄져야 할 부분을 잘못된 위치에 저장하는 것임.

  2. ENUM 멤버 리스트를 변경하는 비용이 큼

    ENUM 컬럼의 멤버 리스트를 변경하면 ALTER TABLE 명령을 사용해 테이블을 재구성해야 함. 이 과정은 매우 비싸며 시간이 많이 소요될 수 있음.
    특히 큰 테이블에서 이 작업은 리소스를 많이 차지하고 오랜 시간이 걸림. 반면, 참조 테이블을 사용하면 변경이 훨씬 간단하고 저렴함.

  3. 추가 속성이나 관련 정보를 추가하기 어려움

    ENUM 컬럼에는 관련 정보를 추가할 방법이 없음.
    반면, 참조 테이블에서는 쉽게 새로운 속성을 추가할 수 있음. 예를 들어, 테이블 열목록에 각 컬럼을 추가해야 할 경우, 참조 테이블에서는 열을 추가하면 됨. ENUM에서는 이와 같은 확장이 불가능함.

  4. DISTINCT ENUM 멤버 목록을 얻기 어려움

    폼의 드롭다운 목록을 채우기 위해 가능한 값을 추출하려면 ENUM 컬럼에서 모든 값을 쉽게 가져올 수 없음.
    참조 테이블에서는 SELECT * FROM table을 사용하여 쉽게 값을 추출할 수 있음. ENUM에서는 INFORMATION_SCHEMA를 통해 복잡한 쿼리를 작성해야 함.

  5. ENUM 컬럼이 최적화에 미치는 영향이 제한적이거나 미미할 수 있음

    ENUM이 최적화를 제공한다고 하지만, 이는 실제로 큰 성능 향상을 제공하지 않을 수 있음.
    참조 테이블을 사용하는 것이 성능에 큰 영향을 주지 않을 수 있으며, 실제 데이터 셋으로 벤치마킹하여 확인하는 것이 좋음(실제 이는 비교해보면서 써봐야함).

  6. 다른 테이블에서 ENUM 멤버 리스트를 재사용할 수 없음

    ENUM 컬럼의 멤버 리스트는 다른 테이블에서 쉽게 재사용할 수 없음. 참조 테이블에서는 동일한 데이터 세트를 여러 테이블에 연결하거나 조인할 수 있어 데이터 일관성을 유지하기 쉬움.

  7. ENUM 컬럼의 주의점

    잘못된 값이 삽입되면 빈 문자열('')로 설정되는 등 ENUM에는 여러 주의점이 있음.

  8. 다른 DBMS로의 이식성이 제한적임

    ENUM은 표준 SQL이 아니기 때문에 다른 DBMS에서는 지원하지 않는 경우가 많음.
    데이터베이스 시스템을 변경해야 할 때 ENUM을 처리하는 데 추가 작업이 필요하며, 이는 복잡성을 증가시킴.

📋 ENUM을 사용해도 괜찮은 경우

  • 변경되지 않는 고정 값 세트를 저장할 때: 잘 정의된 고정 값 세트를 저장할 때 적합함.
  • 관련 정보를 추가할 필요가 없을 때: 카드 게임의 카드 슈트처럼 추가 속성을 저장할 필요가 없을 때 적합함.
  • 멤버 리스트가 2개 이상 20개 이하일 때: ENUM은 최대 65,535개의 값을 저장할 수 있지만, 실제로는 20개 이하일 때만 관리하기 쉬워짐.

📋 결론

개발 및 유지보수 관점에서 참조 테이블을 사용하는 것이 대부분의 경우 더 유리함.
성능 문제는 실제로 발생했을 때 해결하는 것이 좋으며, 미리 최적화하는 것은 권장되지 않음. ENUM은 단순하고 고정된 값 세트를 저장하는 데 유용할 수 있지만, 유연성과 확장성을 고려하면 참조 테이블이 더 나은 선택임.
따라서 둘다 테스트를 하거나 비교해가면서 쓰자. 왠만하면 참조테이블로 하는 것이 좋다.

⚙️ 출처: https://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

0개의 댓글