Development Tip

utf8_general_ci와 utf8_unicode_ci의 차이점은 무엇입니까?

yourdevel 2020. 9. 27. 14:07
반응형

utf8_general_ci와 utf8_unicode_ci의 차이점은 무엇입니까?


utf8_general_ci사이 utf8_unicode_ci에 성능면에서 차이가 있습니까?


이 두 데이터 정렬은 모두 UTF-8 문자 인코딩 용입니다. 차이점은 텍스트를 정렬하고 비교하는 방법에 있습니다.

참고 : MySQL은 5.5.3부터 사용한다 utf8mb4보다는 utf8. 둘 다 UTF-8 인코딩을 참조하지만 이전 버전 utf8에는 0xFFFD 이상으로 번호가 지정된 문자를 사용하지 못하도록하는 MySQL 관련 제한이 있습니다.

주요 차이점

  • utf8mb4_unicode_ci 범용 정렬 및 비교를위한 공식 유니 코드 규칙을 기반으로하며 광범위한 언어로 정확하게 정렬됩니다.

  • utf8mb4_general_ci속도를 향상시키기 위해 고안된 많은 단축키를 사용하면서 할 수있는 것만큼이나 할 수있는 것을 목표로하는 단순화 된 정렬 규칙 세트입니다. 유니 코드 규칙을 따르지 않으며 특정 언어 나 문자를 사용할 때와 같은 일부 상황에서 바람직하지 않은 정렬 또는 비교가 발생합니다.

    최신 서버에서 이러한 성능 향상은 거의 무시할 수 있습니다. 이것은 서버가 오늘날 컴퓨터의 CPU 성능의 극히 일부를 차지하던시기에 고안되었습니다.

참고 :이 지금의 업데이트 된 버전이 존재 utf8mb4_unicode_ci이라 불리는 utf8mb4_0900_ai_ci-이 유니 코드 버전 9.0의 변화를 기반으로, 그리고 분명히 빠르게도있다. 새로운 이름 지정 체계를 채택 0900하여 유니 코드 버전이고 ai악센트를 구분하지 않음을 의미합니다. 이전과 마찬가지로 utf8mb4_unicode_ci문자의 악센트는 중요하지 않은 것으로 간주됩니다.

utf8mb4_unicode_ci오버의 이점utf8mb4_general_ci

utf8mb4_unicode_ci정렬 및 비교에 유니 코드 규칙을 사용하는은 광범위한 언어에서 그리고 다양한 특수 문자를 사용할 때 올바른 정렬을 위해 상당히 복잡한 알고리즘을 사용합니다. 이러한 규칙은 언어 별 규칙을 고려해야합니다. 모두가 우리가 '알파벳 순서'라고 부르는 문자를 정렬하는 것은 아닙니다.

라틴어 (예 : "유럽") 언어에 관한 한, utf8mb4_general_ciMySQL 의 유니 코드 정렬과 단순화 된 정렬 사이에는 큰 차이가 없지만 여전히 몇 가지 차이점이 있습니다.

  • 예를 들어, 유니 코드 데이터 정렬은 "ss"와 같은 "ß"와 "OE"와 같은 "Œ"을 해당 문자를 사용하는 사람들이 일반적으로 원하는대로 utf8mb4_general_ci정렬하는 반면 단일 문자로 정렬합니다 (각각 "s"및 "e"와 같음). .

  • 일부 유니 코드 문자는 무시할 수있는 것으로 정의됩니다. 즉, 정렬 순서에 포함되지 않아야하며 비교는 대신 다음 문자로 이동해야합니다. utf8mb4_unicode_ci제대로 처리합니다.

아시아 언어 또는 알파벳이 다른 언어와 같은 비 라틴어 언어에서는 유니 코드 정렬과 단순화 된 정렬 간에 훨씬 더 많은 차이 가있을 수 있습니다 utf8mb4_general_ci. 의 적합성은 utf8mb4_general_ci사용되는 언어에 따라 크게 달라집니다. 일부 언어의 경우 매우 부적절합니다.

무엇을 사용해야합니까?

utf8mb4_general_ci성능 차이가 중요 할만큼 CPU 속도가 충분히 낮은 지점을 남겨 두었 기 때문에 더 이상 사용할 이유가 거의 없습니다 . 데이터베이스는 이것 이외의 다른 병목 현상에 의해 거의 확실히 제한됩니다.

과거 utf8mb4_general_ci에는 성능 비용을 정당화 할만큼 정확한 정렬이 중요 할 때를 제외하고 일부 사람들이 사용하도록 권장했습니다 . 오늘날 그 성능 비용은 거의 사라졌고 개발자들은 국제화를 더 심각하게 다루고 있습니다.

정확성보다 속도가 더 중요하다면 정렬을 전혀하지 않는 것이 좋을 수도 있다는 주장이 있습니다. 정확할 필요가없는 경우 알고리즘을 더 빠르게 만드는 것은 간단합니다. 따라서 utf8mb4_general_ci속도상의 이유로 필요하지 않을 수도 있고 정확성상의 이유로도 적합하지 않은 절충안입니다.

내가 추가 할 또 하나는 응용 프로그램이 영어 만 지원한다는 것을 알고 있더라도 여전히 사람들의 이름을 처리해야 할 수 있다는 것입니다. 다른 언어에서 사용되는 문자를 포함 할 수 있으며 올바르게 정렬하는 것이 중요합니다. . 모든 것에 유니 코드 규칙을 사용하면 매우 똑똑한 유니 코드 사람들이 정렬 작업을 제대로 수행하기 위해 매우 열심히 일했다는 마음의 평화를 더할 수 있습니다.

부품의 의미

첫째, ci입니다 대소 문자를 구분하지 정렬 및 비교. 즉, 텍스트 데이터에 적합하며 대소 문자는 중요하지 않습니다. 다른 유형의 데이터 정렬은 cs대소 문자가 중요한 텍스트 데이터의 경우 (대소 문자 구분) bin, 인코딩이 일치해야하는 경우에는 비트 단위로, 실제로 인코딩 된 이진 데이터 인 필드 (예 : Base64). 대 / 소문자 구분 정렬은 이상한 결과를 초래하고 대 / 소문자 구분 비교로 인해 대소 문자 만 다른 중복 값이 ​​발생할 수 있으므로 대소 문자 구분 데이터 정렬은 텍스트 데이터에 적합하지 않습니다. 대소 문자가 중요하면 구두점을 무시할 수 있습니다. 등도 중요 할 수 있으며 이진 데이터 정렬이 더 적절할 수 있습니다.

다음으로 unicode또는 general특정 정렬 및 비교 규칙을 나타냅니다. 특히 텍스트가 정규화되거나 비교되는 방식입니다. 거기 utf8mb4 문자 인코딩에 대한 규칙의 많은 다른 세트와 함께입니다 unicodegeneral이되는 것을 잘 가능한 모든 언어로 작업을 시도하기보다는 하나의 특정의 하나. 이 두 가지 규칙 세트의 차이점이이 답변의 주제입니다. 최신 규칙 세트에는 0900Unicode 9.0 및 unicode_520Unicode 5.2 참조가 포함됩니다.

그리고 마지막으로 utf8mb4내부적으로 사용되는 문자 인코딩입니다. 이 답변에서는 유니 코드 기반 인코딩에 대해서만 이야기하고 있습니다.


내가 사용 사이의 성능 차이가 뭔지 알고 싶어 utf8_general_ci하고 utf8_unicode_ci,하지만 난 벤치 마크에게 자신을 만들기로 결정 그래서 나는 인터넷에 나와있는 벤치 마크를 찾지 못했습니다.

500,000 개의 행이있는 매우 간단한 테이블을 만들었습니다.

CREATE TABLE test(
  ID INT(11) DEFAULT NULL,
  Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;

그런 다음이 저장 프로 시저를 실행하여 임의의 데이터로 채웠습니다.

CREATE PROCEDURE randomizer()
BEGIN
  DECLARE i INT DEFAULT 0;
  DECLARE random CHAR(20) ;
  theloop: loop
    SET random = CONV(FLOOR(RAND() * 99999999999999), 20, 36);
    INSERT INTO test VALUES (i+1, random);
    SET i=i+1;
    IF i = 500000 THEN
      LEAVE theloop;
    END IF;
  END LOOP theloop;
END

그런 다음 simple SELECT, SELECTwith LIKE및 sorting ( SELECTwith ORDER BY) 을 벤치마킹하기 위해 다음 저장 프로 시저를 만들었습니다 .

CREATE PROCEDURE benchmark_simple_select()
BEGIN
  DECLARE i INT DEFAULT 0;
  theloop: loop
    SELECT *
    FROM test
    WHERE Description = 'test' COLLATE utf8_general_ci;
    SET i = i + 1;
    IF i = 30 THEN
      LEAVE theloop;
    END IF;
  END LOOP theloop;
END;

CREATE PROCEDURE benchmark_select_like()
BEGIN
  DECLARE i INT DEFAULT 0;
  theloop: loop
    SELECT *
    FROM test
    WHERE Description LIKE '%test' COLLATE utf8_general_ci;
    SET i = i + 1;
    IF i = 30 THEN
      LEAVE theloop;
    END IF;
  END LOOP theloop;
END;

CREATE PROCEDURE benchmark_order_by()
BEGIN
  DECLARE i INT DEFAULT 0;
  theloop: loop
    SELECT *
    FROM test
    WHERE ID > FLOOR(1 + RAND() * (400000 - 1))
    ORDER BY Description COLLATE utf8_general_ci LIMIT 1000;
    SET i = i + 1;
    IF i = 10 THEN
      LEAVE theloop;
    END IF;
  END LOOP theloop;
END;

위의 저장 프로 시저에서는 utf8_general_ci데이터 정렬이 사용되었지만 물론 테스트 중에는 utf8_general_ciutf8_unicode_ci.

나는 (5 회 저장 프로 시저 각 조합에 대한 5 회 호출 utf8_general_ci과 5 회 utf8_unicode_ci) 한 후 평균값을 계산 하였다.

내 결과는 다음과 같습니다.

benchmark_simple_select()

  • 포함 utf8_general_ci: 9,957ms
  • with utf8_unicode_ci: 10,271 ms

In this benchmark using utf8_unicode_ci is slower than utf8_general_ci by 3.2%.

benchmark_select_like()

  • with utf8_general_ci: 11,441 ms
  • with utf8_unicode_ci: 12,811 ms

In this benchmark using utf8_unicode_ci is slower than utf8_general_ci by 12%.

benchmark_order_by()

  • with utf8_general_ci: 11,944 ms
  • with utf8_unicode_ci: 12,887 ms

In this benchmark using utf8_unicode_ci is slower than utf8_general_ci by 7.9%.


This post describes it very nicely.

In short: utf8_unicode_ci uses the Unicode Collation Algorithm as defined in the Unicode standards, whereas utf8_general_ci is a more simple sort order which results in "less accurate" sorting results.


See the mysql manual, Unicode Character Sets section:

For any Unicode character set, operations performed using the _general_ci collation are faster than those for the _unicode_ci collation. For example, comparisons for the utf8_general_ci collation are faster, but slightly less correct, than comparisons for utf8_unicode_ci. The reason for this is that utf8_unicode_ci supports mappings such as expansions; that is, when one character compares as equal to combinations of other characters. For example, in German and some other languages “ß” is equal to “ss”. utf8_unicode_ci also supports contractions and ignorable characters. utf8_general_ci is a legacy collation that does not support expansions, contractions, or ignorable characters. It can make only one-to-one comparisons between characters.

So to summarize, utf_general_ci uses a smaller and less correct (according to the standard) set of comparisons than utf_unicode_ci which should implement the entire standard. The general_ci set will be faster because there is less computation to do.


In brief words:

If you need better sorting order - use utf8_unicode_ci (this is the preferred method),

but if you utterly interested in performance - use utf8_general_ci, but know that it is a little outdated.

The differences in terms of performance are very slight.


Some details (PL)

As we can read here (Peter Gulutzan) there is difference on sorting/comparing polish letter "Ł" (L with stroke - html esc: Ł) (lower case: "ł" - html esc: ł) - we have following assumption:

utf8_polish_ci      Ł greater than L and less than M
utf8_unicode_ci     Ł greater than L and less than M
utf8_unicode_520_ci Ł equal to L
utf8_general_ci     Ł greater than Z

In polish language letter Ł is after letter L and before M. No one of this coding is better or worse - it depends of your needs.


According to this post, there is a considerably large performance benefit on MySQL 5.7 when using utf8mb4_general_ci in stead of utf8mb4_unicode_ci: https://www.percona.com/blog/2019/02/27/charset-and-collation-settings-impact-on-mysql-performance/

참고URL : https://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci

반응형