'utf8_general_ci'와 'utf8_unicode_ci'는 성능 면에서 어떤 차이가 있나요?
이 두 데이터 정렬은 모두 UTF-8 문자 인코딩을 위한 것입니다. 차이점은 텍스트가 정렬되고 비교되는 방식에 있습니다.
참고: utf8
이 아닌 utf8mb4
를 사용해야 합니다. 둘 다 UTF-8 인코딩을 참조하지만, 이전 utf8
에는 0xFFFD 이상의 문자를 사용할 수 없는 MySQL 관련 제한이 있었습니다.
참고: 최신 버전의 MySQL에는 업데이트된 유니코드 정렬 규칙이 있으며, 유니코드 9.0에 기반한 규칙의 경우 utf8mb4_0900_ci
와 같은 이름으로 사용할 수 있으며, 이에 상응하는 일반
변형은 없습니다.*
주요 차이점
utf8mb4_unicode_ci
는 범용 정렬 및 비교를 위한 공식 유니코드 규칙을 기반으로 하며, 다양한 언어에서 정확하게 정렬합니다.utf8mb4_general_ci
는 속도를 향상시키기 위해 설계된 많은 단축키를 사용하면서 가능한 한 잘 정렬하는 것을 목표로 하는 단순화된 정렬 규칙 집합입니다. 이 규칙은 유니코드 규칙을 따르지 않으며 특정 언어나 문자를 사용할 때와 같은 일부 상황에서는 바람직하지 않은 정렬 또는 비교를 초래할 수 있습니다.
최신 서버에서는 이러한 성능 향상 효과가 거의 무시할 수 있을 정도입니다. 서버의 CPU 성능이 오늘날 컴퓨터의 극히 일부에 불과하던 시절에 고안된 것이기 때문입니다.
참고: 현재 'utf8mb4_unicode_ci'의 업데이트 버전인 'utf8mb4_0900_ai_ci'가 존재하며, 이는 유니코드 버전 9.0의 변경 사항을 기반으로 하며 더 빨라진 것으로 보입니다. '0900'은 유니코드 버전이고 'ai'는 악센트에 민감하지 않음을 의미하는 새로운 명명 체계를 채택하여 이전의 utf8mb4_unicode_ci
와 마찬가지로 문자의 악센트는 중요하지 않은 것으로 간주됩니다..
utf8mb4_general_ci
에 비해 utf8mb4_unicode_ci
의 장점
유니코드 규칙을 정렬 및 비교에 사용하는 utf8mb4_unicode_ci
는 다양한 언어와 다양한 특수 문자를 사용할 때 올바른 정렬을 위해 상당히 복잡한 알고리즘을 사용합니다. 이러한 규칙은 언어별 규칙을 고려해야 하는데, 모든 사람이 알파벳 순서로 문자를 정렬하는 것은 아닙니다.
라틴어(즉, 유럽어)의 경우 유니코드 정렬과 MySQL의 간소화된 utf8mb4_general_ci
정렬 간에 큰 차이는 없지만 여전히 몇 가지 차이점이 있습니다:utf8mb4_general_ci
는 단일 문자(아마도 각각 는 이를 올바르게 처리합니다. 아시아 언어나 알파벳이 다른 언어와 같이 라틴어가 아닌 언어의 경우 유니코드 정렬과 단순화된
utf8mb4_general_ci정렬 간에 많은 *더 많은* 차이가 있을 수 있습니다. utf8mb4_general_ci
의 적합성은 사용되는 언어에 따라 크게 달라집니다. 일부 언어의 경우 상당히 부적절할 수 있습니다.
무엇을 사용해야 하나요?
성능 차이가 중요할 정도로 CPU 속도가 낮은 시점은 지났기 때문에 더 이상 utf8mb4_general_ci
를 사용할 이유가 거의 없습니다. 데이터베이스는 이 외에도 다른 병목 현상에 의해 제한될 가능성이 높습니다.
과거에는 정확한 정렬이 성능 비용을 정당화할 만큼 중요한 경우를 제외하고는 utf8mb4_general_ci
를 사용하도록 권장하는 사람들도 있었습니다. 오늘날 이러한 성능 비용은 거의 사라졌고 개발자들은 국제화를 더 중요하게 여기고 있습니다.
정확성보다 속도가 더 중요하다면 정렬을 전혀 하지 않는 것이 낫다는 주장이 제기되고 있습니다. 알고리즘이 정확할 필요가 없다면 알고리즘을 더 빠르게 만드는 것은 사소한 일입니다. 따라서 utf8mb4_general_ci
는 속도상의 이유로 필요하지 않을 수도 있고 정확도상의 이유로 적합하지 않을 수도 있는 절충안입니다.
한 가지 더 덧붙이자면, 애플리케이션이 영어만 지원한다고 해도 사람 이름을 처리해야 할 수 있으며, 여기에는 다른 언어에서 사용되는 문자가 포함될 수 있으므로 올바르게 정렬하는 것이 중요합니다. 모든 것에 유니코드 규칙을 사용하면 매우 똑똑한 유니코드 개발자들이 정렬을 제대로 작동시키기 위해 많은 노력을 기울였다는 사실에 안심할 수 있습니다.
각 부분의 의미*
첫째, ci
는 대소문자를 구분하지 않는* 정렬 및 비교를 위한 것입니다. 즉, 텍스트 데이터에 적합하며 대소문자는 중요하지 않습니다. 다른 정렬 유형으로는 대소문자가 중요한 텍스트 데이터에 적합한 cs
(대소문자 구분)와 인코딩이 비트 단위로 일치해야 하는 경우에 적합한 bin
이 있는데, 이는 실제 인코딩된 이진 데이터(예: Base64 포함)인 필드에 적합합니다. 대/소문자를 구분하여 정렬하면 이상한 결과가 나오고 대/소문자를 구분하여 비교하면 대/소문자만 다른 값이 중복될 수 있으므로 대/소문자 구분 데이터 정렬은 텍스트 데이터에 적합하지 않습니다. 대/소문자가 중요한 경우 무시할 수 있는 구두점 등도 중요할 수 있으며 이진 데이터 정렬이 더 적합할 수 있습니다.
다음으로, '유니코드' 또는 '일반'은 특정 정렬 및 비교 규칙, 특히 텍스트가 정규화되거나 비교되는 방식을 나타냅니다. utf8mb4 문자 인코딩에는 여러 가지 규칙 집합이 있으며, '유니코드'와 '일반'은 특정 언어가 아닌 가능한 모든 언어에서 잘 작동하도록 시도하는 두 가지 규칙입니다. 이 두 규칙 세트의 차이점이 이 답변의 주제입니다. 유니코드는 유니코드 4.0의 규칙을 사용한다는 점에 유의하세요. 최신 버전의 MySQL은 유니코드 5.2의 규칙을 사용하는 규칙 집합
유니코드_520과 유니코드 9.0의 규칙을 사용하는
0900(유니코드_부분 삭제)을 추가합니다. 마지막으로
utf8mb4`는 물론 내부적으로 사용되는 문자 인코딩입니다. 이 답변에서는 유니코드 기반 인코딩에 대해서만 이야기하고 있습니다.내가 원하는 게 무엇인지, but I '와' utf8_unicode_ci '성능' utf8_general_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;
그럼 내가 접수됨 정보기술 (it) 이 랜덤 데이터로 실행하여 저장 프로시저:
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
그럼 내가 만든 다음 절차는 단순한 '선택', '선택' 을 (를) 'LIKE' 저장됩니까 벤치마트, 정렬 ('선택' 을 (를) '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_unicode_ci utf8_general_ci'.
각 각 저장 프로시저 5 배 불렀는데 collation (5 회 5 번 '과' '대한' utf8_general_ci utf8_unicode_ci) 한 후 계산됩니까 평균 값입니다.
나의 결과는 다음과 같습니다.
'benchmark_simple_select ()' *
utf8_general_ci '와': 9,957 밀리초입니다
utf8_unicode_ci '와': 10,271 밀리초입니다
이 벤치마트 utf8_unicode_ci '는' utf8_general_ci 3.2% 포인트 보다 느린 사용하여 ''.
'benchmark_select_like ()' *
utf8_general_ci '와': 11,441 밀리초입니다
utf8_unicode_ci '와': 12,811 밀리초입니다
이 벤치마트 utf8_unicode_ci '는' utf8_general_ci 12% 포인트 보다 느린 사용하여 ''.
'benchmark_order_by ()' *
utf8_general_ci '와': 11,944 밀리초입니다
utf8_unicode_ci '와': 12,887 밀리초입니다
이 벤치마트 utf8_unicode_ci '는' utf8_general_ci 7.9% 포인트 보다 느린 사용하여 ''.
mysql 매뉴얼의 유니코드 문자 집합 섹션을 참조하십시오: 모든 유니코드 문자 집합의 경우,
_일반_ci 콜레이션을 사용하여 수행되는 작업은 일반_ci 콜레이션을 사용하여 수행되는 연산은 _유니코드_ci 콜레이션보다 빠릅니다. 예를 들어, 다음과 같은 비교는 utf8_general_ci 콜레이션이 더 빠릅니다, 하지만 정확도는 약간 떨어집니다. utf8_unicode_ci에 대한 비교. 그리고 그 이유는 utf8_unicode_ci는 다음과 같은 매핑을 지원합니다. 확장으로; 즉, 하나의 문자가 다음과 같은 것으로 비교됩니다. 다른 문자의 조합. For 예를 들어, 독일어 및 일부 다른 언어 "ß"는 "ss"와 같습니다. UTF8_UNICODE_CI는 다음도 지원합니다. 축약 및 무시할 수 있는 문자도 지원합니다. utf8_general_ci는 레거시 콜레이션입니다. 확장을 지원하지 않습니다, 축약 또는 무시할 수 있는 문자를 지원하지 않는 레거시 콜레이션입니다. 일대일 비교만 가능합니다. 문자 간 비교만 가능합니다.
요약하자면, utf_general_ci는 전체 표준을 구현해야 하는 utf_unicode_ci보다 더 작고 덜 정확한(표준에 따라) 비교 집합을 사용합니다. 일반_ci 집합은 수행해야 할 계산이 적기 때문에 더 빠릅니다.
사용 할 경우 정렬 순서를 utf8_unicode_ci (이것이 더 좋은 방법) ',' 더 나은
하지만 결코 '-' utf8_general_ci 사용할 경우 성능 관심이 있지만 것을 알고 조금 오래된.
성능 면에서 아주 약간의 차이가 있다.
아니라 우리가 읽을 수 있는 [here] [2] ( 피터 구루츠런 ) / 비교 정렬, Ł" " 란드어 서신입니다 대한 차이 없다. (L) 와 선 - html esc: # 321 &, ',') (소문자: " ł"; - html esc: # '&, 322,') - 우리는 다음과 같은 가정:
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'. 이 코드는 또는 그 누구도 더 달려 - 고객의 요구 사항을.
[2]: 9604%20 %e2%80%93%20user3399549%20mar% 209%20%2714%20at% 2021 15? id = https://bugs.mysql.com/bug.php