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_ci
MySQL 의 유니 코드 정렬과 단순화 된 정렬 사이에는 큰 차이가 없지만 여전히 몇 가지 차이점이 있습니다.
예를 들어, 유니 코드 데이터 정렬은 "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 문자 인코딩에 대한 규칙의 많은 다른 세트와 함께입니다 unicode
및 general
이되는 것을 잘 가능한 모든 언어로 작업을 시도하기보다는 하나의 특정의 하나. 이 두 가지 규칙 세트의 차이점이이 답변의 주제입니다. 최신 규칙 세트에는 0900
Unicode 9.0 및 unicode_520
Unicode 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
, SELECT
with LIKE
및 sorting ( SELECT
with 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_ci
및 utf8_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/
'Development Tip' 카테고리의 다른 글
특정 속성에 대한 LINQ의 Distinct () (0) | 2020.09.27 |
---|---|
C 전처리 기가“linux”라는 단어를 상수“1”로 해석하는 이유는 무엇입니까? (0) | 2020.09.27 |
stderr로 출력하는 에코 (0) | 2020.09.27 |
DataTable에 대한 LINQ 쿼리 (0) | 2020.09.27 |
Visual Studio가 Windows 8에서 항상 관리자 권한으로 실행되도록 할 수 있습니까? (0) | 2020.09.27 |