콘텐츠로 이동

2024 04 07

2024-04-07

MySQL Charset, Collation

참고: https://sshkim.tistory.com/128 참고: https://www.lesstif.com/dbms/mysql-8-character-set-collation-91947077.html 참고: https://www.lesstif.com/dbms/mysql-character-sets-collations-9437311.html

  • 배경
    • 데이터베이스도 "더 작은 공간으로" "더 빠른 처리"가 가능하게 진화하였음
    • ex) true/false 저장시...
      • boolean > char(0, 1) > int(0, 1)
  • Encoding
    • character나 grapheme을 어떻게 binary로 표시할지 규정한 방법
      • ex) ASCII, ISO-8859-1/LATIN-1, EUC-KR
    • 대표적인게 UNICODE
      • UTF-8: 문자당 1~4 바이트 (호환성 탑, 복잡한 코드 체계, 인/디코딩 때매 느린 속도, 저장공간 많이 먹음)
      • UTF-16: 문자당 2 or 4 바이트
      • UTF-32: 문자당 4 바이트 (처리속도 탑)
  • Charset (문자 집합)
    • [UTF-8 Charset (다국어 언어셋)]
      • 실생활의 모든 텍스트 데이터를 저장하고자 나옴
      • UTF-8로는 1~4 바이트까지 저장 가능 (가변 바이트)
      • 전 세계 모든 언어를 다룰 수 있는 "다국어" 언어셋
      • MySQL/MariaDB 도 UTF-8 지원
        • 전세계 모든 언어가 21bit에 저장되기에, MySQL은 utf8을 3바이트 가변 자료형으로 설정
        • 그런데 최근 나온 4바이트 문자열 "이모지"의 등장으로 utf8에 값 저장시 값 손실!
        • 널리 사용되던 MySQL 환경에서 charset: utf8, collation: utf8_general_ci 인데 이게 환경에서 문제됨
    • [4바이트 UTF-8 Charset (utf8mb4)]
      • 원래 설계대로 4바이트 UTF-8 문자열 저장 자료형 추가 => 이게 utf8mb4
      • Emoji 문자열이 4바이트라서 뚝딱 처리가능
    • MySQL 지원 Charset
      mysql> show character set;
      
      +----------+---------------------------------+---------------------+--------+
      | Charset  | Description                     | Default collation   | Maxlen |
      +----------+---------------------------------+---------------------+--------+
      | armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
      | ascii    | US ASCII                        | ascii_general_ci    |      1 |
      | ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
      | utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
      | utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
      | utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
      | utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
      | utf8mb4  | UTF-8 Unicode                   | utf8mb4_0900_ai_ci  |      4 |
      +----------+---------------------------------+---------------------+--------+
      
  • Collation (정렬)
    • 텍스트 데이터를 정렬(order by)할 때 사용!
    • TEXT 자료형에서만 사용할 수 있는 속성!
      • text에서 a 와 b 중에 뭐가 큰지 어찌알지?
      • ORDER BY text ASC
    • [utf8_bin(utf8mb4_bin)]
      • 바이너리 값 그대로 정렬
        • ex) A > B > a > b
    • [utf8_general_ci(utf8mb4_general_ci)]
      • 텍스트 정렬시 a다음 b가 나오는게 맞다는 정렬방식
      • 바이너리 한차례 가공
        • ex) A > a > B > b
    • [utf8_unicode_ci(utf8mb4_unicode_ci)]
      • 조금 더 사람에 맞게 정렬
      • 한영중일 사용환경에서는 general_ci, unicode_ci 결과 동일
    • MySQL 지원 Collation
      mysql>  SHOW COLLATION;
      
      +----------------------------+----------+-----+---------+----------+---------+---------------+
      | Collation                  | Charset  | Id  | Default | Compiled | Sortlen | Pad_attribute |
      +----------------------------+----------+-----+---------+----------+---------+---------------+
      | armscii8_bin               | armscii8 |  64 |         | Yes      |       1 | PAD SPACE     |
      | armscii8_general_ci        | armscii8 |  32 | Yes     | Yes      |       1 | PAD SPACE     |
      | ascii_bin                  | ascii    |  65 |         | Yes      |       1 | PAD SPACE     |
      | ascii_general_ci           | ascii    |  11 | Yes     | Yes      |       1 | PAD SPACE     |
      | utf8mb4_0900_ai_ci         | utf8mb4  | 255 | Yes     | Yes      |       0 | NO PAD        |
      | utf8mb4_0900_as_ci         | utf8mb4  | 305 |         | Yes      |       0 | NO PAD        |
      | utf8mb4_0900_as_cs         | utf8mb4  | 278 |         | Yes      |       0 | NO PAD        |
      | utf8mb4_0900_bin           | utf8mb4  | 309 |         | Yes      |       1 | NO PAD        |
      | utf8mb4_bin                | utf8mb4  |  46 |         | Yes      |       1 | PAD SPACE     |
      | utf8mb4_croatian_ci        | utf8mb4  | 245 |         | Yes      |       8 | PAD SPACE     |
      | utf8mb4_cs_0900_ai_ci      | utf8mb4  | 266 |         | Yes      |       0 | NO PAD        |
      | utf8mb4_cs_0900_as_cs      | utf8mb4  | 289 |         | Yes      |       0 | NO PAD        |
      +----------------------------+----------+-----+---------+----------+---------+---------------+
      
  • MySQL 8의 charset, collation 변경 사항
    • MySQL 8의 기본 charset: latin-1 => utf8mb4
    • MySQL 8의 기본 collation: utf8mb4_0900_ai_ci
      • utf8mb4: 각 character 최대 4바이트의 utf8 인코딩 지원
      • 0900: Unicode의 collation algorithm 9.0.0 지원
      • ai: accent insensitivity. (e, è, é, ê, ë 같은 문자로 취급 )
      • ci: case insensitivity. (p, P 같은 문자로 취급)
  • Collation 변경에 어찌 대처하는가?
    • Collation 변경에 따라 정렬, index, pk, unique 까지 영향 줌.
    • 다개국어 DB는 collation 변경 영향도 측정이 어려움

ES index templates

참고: https://developer-jp.tistory.com/41 참고: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/index-templates.html

  • 개요
    • 인덱스 템플릿을 통해 인덱스 생성 시 어떻게 구성할지 알려줄 수 있음
    • 인덱스 생성의 기초로 템플릿의 설정이 반영됨
  • 템플릿의 구성요소
    • 2가지의 템플릿 구성 요소가 있음
      1. index template (더 큰 개념인가보다)
        • 컴포넌트 템플릿 모음을 포함 가능
        • mapping, setting, alias 설정 가능
      2. component template
        • 재사용 가능한 블럭
        • mapping, setting, alias 설정 가능
        • 인덱스 템플릿 구성 가능하나, 인덱스 집합에 직접 적용되진 X
  • 컴포넌트 템플릿
    • 다수의 템플릿 관리하는데 문제 있을 수 있음
      • 인덱스 템플릿간의 중복 => 클러스터 상태 커짐
      • 모든 인덱스 템플릿 변경 시, 각 템플릿 수동 변경
      • 인덱스가 여러 템플릿과 일치시, opensearch 자체적 병합 시도하며 예기치 않은 병합
    • 컴포넌트를 통해 공통 설정, 매핑, 별칭 재사용 가능한 블록으로 추상화!
  • Index template 조건
    1. Composable template이 먼저 나와야함.
      • Composable template들의 조건에 아무것도 맞지 않으면, legacy template으로 처리 될 수 있음
    2. Index가 명시적으로 생성되고, 인덱스 템플릿과도 일치한다면, 인덱스 생성 요청의 설정이 가장 우선순위임
    3. 인덱스 템플릿의 세팅은 구성 요소 템플릿의 설정보다 우선함
    4. 새 데이터 스트림, 인덱스가 둘 이상의 인덱스 템플릿과 일치한다면, 우선순위 높은 인덱스 템플릿 채택
  • 예시

    • component template 생성
      PUT _component_template/component_template1
      {
        "template": {
          "mappings": {
            "properties": {
              "@timestamp": {
                "type": "date"
              }
            }
          }
        }
      }
      
      PUT _component_template/runtime_component_template
      {
        "template": {
          "mappings": {
            "runtime": { 
              "day_of_week": {
                "type": "keyword",
                "script": {
                  "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
                }
              }
            }
          }
        }
      }
      
    • index template 생성
      PUT _index_template/template_1
      {
        "index_patterns": ["te*", "bar*"],
        "template": {
          "settings": {
            "number_of_shards": 1
          },
          "mappings": {
            "_source": {
              "enabled": true
            },
            "properties": {
              "host_name": {
                "type": "keyword"
              },
              "created_at": {
                "type": "date",
                "format": "EEE MMM dd HH:mm:ss Z yyyy"
              }
            }
          },
          "aliases": {
            "mydata": { }
          }
        },
        "priority": 500,
        "composed_of": ["component_template1", "runtime_component_template"], 
        "version": 3,
        "_meta": {
          "description": "my custom"
        }
      }
      
  • 활용처
    • 이미 정의된 mapping, setting 그대로 새 인덱스 초기화 가능
    • 지속적으로 인덱싱하는 Log data 라면, index가 동일한 샤드/복제본 같도록 인덱스 템플릿 정의 가능