UTF8_GENERAL_CI와 UTF8_UNICODE_CI의 차이점은 무엇입니까?
-
12-09-2019 - |
문제
사이 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
유니 코드 9.0을 참조하고 unicode_520
유니 코드 5.2 참조.
그리고 마지막으로, utf8mb4
물론 내부적으로 사용되는 캐릭터 인코딩입니다. 이 답변에서 나는 유니 코드 기반 인코딩에 대해서만 이야기하고 있습니다.
다른 팁
사용 사이의 성능 차이가 무엇인지 알고 싶었습니다. utf8_general_ci
그리고 utf8_unicode_ci
, 그러나 인터넷에 나열된 벤치 마크를 찾지 못했기 때문에 벤치 마크를 직접 만들기로 결정했습니다.
50 만 행으로 매우 간단한 테이블을 만들었습니다.
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
~와 함께 LIKE
, 및 정렬 (SELECT
~와 함께 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
Collation이 사용되지만 물론 테스트 중에는 두 가지를 모두 사용했습니다. utf8_general_ci
그리고 utf8_unicode_ci
.
각 정제에 대해 각 저장 절차를 5 번 전화했습니다 (5 회 utf8_general_ci
그리고 5 번 utf8_unicode_ci
) 그런 다음 평균 값을 계산했습니다.
내 결과는 다음과 같습니다.
benchmark_simple_select()
- ~와 함께
utf8_general_ci
: 9,957ms - ~와 함께
utf8_unicode_ci
: 10,271 ms
이 벤치 마크에서 utf8_unicode_ci
보다 느립니다 utf8_general_ci
3.2%.
benchmark_select_like()
- ~와 함께
utf8_general_ci
: 11,441ms - ~와 함께
utf8_unicode_ci
: 12,811ms
이 벤치 마크에서 utf8_unicode_ci
보다 느립니다 utf8_general_ci
12%.
benchmark_order_by()
- ~와 함께
utf8_general_ci
: 11,944 ms - ~와 함께
utf8_unicode_ci
: 12,887ms
이 벤치 마크에서 utf8_unicode_ci
보다 느립니다 utf8_general_ci
7.9%
이 게시물 그것을 아주 멋지게 묘사합니다.
요컨대 : UTF8_UNICODE_CI는 유니 코드 표준에 정의 된 UNICODE COLLATION 알고리즘을 사용하는 반면 UTF8_General_Ci는 "정확한"분류 결과를 초래하는보다 간단한 정렬 순서입니다.
MySQL 매뉴얼을 참조하십시오. 유니 코드 문자 세트 부분:
모든 유니 코드 문자 세트의 경우 _general_ci Collation을 사용하여 수행 된 작업은 _unicode_ci Collation의 작업보다 빠릅니다. 예를 들어 UTF8_General_Ci Collation에 대한 비교는 UTF8_unicode_ci의 비교보다 더 빠르지 만 약간 덜 정확합니다. 그 이유는 utf8_unicode_ci가 확장과 같은 매핑을 지원하기 때문입니다. 즉, 한 캐릭터가 다른 문자의 조합과 동일하게 비교할 때입니다. 예를 들어, 독일어와 다른 언어 "ß"는 "SS"와 같습니다. UTF8_UNICODE_CI는 또한 수축과 무시할 수있는 문자를 지원합니다. UTF8_GENERAL_CI는 확장, 수축 또는 무시할 수있는 캐릭터를 지원하지 않는 레거시 콜레이션입니다. 문자간에 일대일 비교 만 만들 수 있습니다.
요약하기 위해 UTF_GENERAL_CI는 UTF_UNICODE_CI보다 작고 덜 정확한 비교 세트를 사용합니다. ~해야 한다 전체 표준을 구현하십시오. General_Ci 세트는 계산이 적기 때문에 더 빠릅니다.
간단한 말로 :
더 나은 정렬 순서가 필요한 경우 - 사용하십시오 utf8_unicode_ci
(이것은 선호되는 방법입니다),
그러나 성능에 완전히 관심이 있다면 사용하십시오 utf8_general_ci
, 그러나 조금 구식이라는 것을 알고 있습니다.
성능 측면의 차이는 매우 적습니다.
일부 세부 사항 (PL)
우리가 읽을 수 있듯이 여기 (피터 굴 루 잔) 폴란드어 문자 "w"(l 뇌졸중 -Html esc와 함께 L을 분류/비교하는 데 차이가 있습니다. Ł
) (소문자 : "ł"-Html ESC : ł
) - 우리는 다음과 같은 가정을 가지고 있습니다.
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
폴란드어 언어 편지로 Ł
편지 후입니다 L
그리고 전에 M
. 이 코딩 중 어느 것도 더 좋거나 나쁘지 않습니다. 그것은 당신의 요구에 달려 있습니다.