utf8_general_ci
와 사이 utf8_unicode_ci
에 성능 측면에서 차이가 있습니까?
답변
이 두 데이터 정렬은 모두 UTF-8 문자 인코딩을위한 것입니다. 차이점은 텍스트를 정렬하고 비교하는 방법에 있습니다.
참고 : MySQL에서는을 사용 utf8mb4
하지 않아야 utf8
합니다. 혼란스럽게도 utf8
초기 MySQL 버전의 결함이있는 UTF-8 구현은 이전 버전과의 호환성을 위해서만 남아 있습니다. 고정 버전의 이름이 지정되었습니다 utf8mb4
.
참고 : 최신 버전의 MySQL은 utf8mb4_0900_ai_ci
유니 코드 9.0을 기반 으로 하는 동등한 규칙 과 같은 이름으로 사용 가능한 등가 _general
변형 없이 유니 코드 정렬 규칙을 업데이트했습니다 . 이 글을 읽는 사람들은 아마도 _unicode
또는 대신에이 새로운 콜 레이션 중 하나를 사용해야 할 것입니다_general
. 새로운 콜 레이션 중 하나를 대신 사용할 수 있다면 아래에 쓰여진 대부분의 내용은 더 이상 관심이 없습니다.
주요 차이점
-
utf8mb4_unicode_ci
범용 정렬 및 비교에 대한 공식 유니 코드 규칙을 기반으로하며 광범위한 언어로 정확하게 정렬됩니다. -
utf8mb4_general_ci
는 속도를 높이기 위해 설계된 많은 단축키를 사용하면서 할 수있을뿐만 아니라 할 수있는 단순한 정렬 규칙 세트입니다. 유니 코드 규칙을 따르지 않으며 특정 언어 나 문자를 사용할 때와 같은 일부 상황에서는 원하지 않는 정렬이나 비교가 발생합니다.최신 서버에서이 성능 향상은 무시할 수 없을 것입니다. 서버가 오늘날 컴퓨터의 CPU 성능의 작은 부분을 차지할 때 고안되었습니다.
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
이되는 것을 잘 가능한 모든 언어로 작업을 시도하기보다는 하나의 특정의 하나. 이 두 규칙 세트의 차이점이이 답변의 주제입니다. unicode
유니 코드 4.0의 규칙 을 사용합니다. 최신 버전의 MySQL unicode_520
은 유니 코드 5.2 의 규칙을 사용하여 규칙 세트 를 추가하고 0900
유니 코드 9.0의 규칙을 사용하여 “unicode_”부분을 삭제합니다.
그리고 마지막으로, 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
: 9957 MS - 로
utf8_unicode_ci
: 10,271 ms
이 벤치 마크에서는 utf8_unicode_ci
사용률이 utf8_general_ci
3.2 % 보다 느립니다 .
benchmark_select_like()
- 로
utf8_general_ci
: 11,441 ms - 로
utf8_unicode_ci
: 12,811 ms
이 벤치 마크에서는 utf8_unicode_ci
사용률이 utf8_general_ci
12 % 보다 느립니다 .
benchmark_order_by()
- 로
utf8_general_ci
: 11,944 ms - 로
utf8_unicode_ci
: 12,887 ms
이 벤치 마크에서는 사용률이 7.9 % utf8_unicode_ci
보다 느립니다 utf8_general_ci
.
답변
이 게시물 은 그것을 아주 잘 설명합니다.
요약하자면, utf8_unicode_ci는 유니 코드 표준에 정의 된대로 Unicode Collation Algorithm을 사용하는 반면, utf8_general_ci는 “정확하지 않은”정렬 결과를 만드는보다 간단한 정렬 순서입니다.
답변
mysql 매뉴얼, Unicode 문자 세트 섹션을 참조하십시오 :
유니 코드 문자 집합의 경우 _general_ci 데이터 정렬을 사용하여 수행 된 작업은 _unicode_ci 데이터 정렬보다 빠릅니다. 예를 들어, utf8_general_ci 데이터 정렬에 대한 비교는 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)
여기서 읽을 수 있듯이 ( Peter Gulutzan ) 폴란드어 문자 “Ł”(획-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
입니다. 이 코딩 중 어느 것도 더 나쁘지 않습니다. 필요에 따라 다릅니다.
답변
정렬과 문자 일치에는 두 가지 큰 차이가 있습니다.
정렬 :
utf8mb4_general_ci
모든 악센트를 제거하고 잘못된 정렬 결과를 생성 할 수있는 하나씩 정렬합니다.utf8mb4_unicode_ci
정확하게 정렬합니다.
문자 매칭
문자가 다르게 일치합니다.
예를 들어, utf8mb4_unicode_ci
당신은 i != ı
있지만 utf8mb4_general_ci
보유하고 있습니다 ı=i
.
예를 들어와 행이 있다고 가정합니다 name="Yılmaz"
. 그때
select id from users where name='Yilmaz';
배열이있는 경우 행을 반환 utf8mb4_general_ci
하지만이 함께 배치되어있는 경우 utf8mb4_unicode_ci
그 것 없는 행을 반환!
우리가 가지고있는 반면에 a=ª
와 ß=ss
에 utf8mb4_unicode_ci
있는 경우가 아니다 utf8mb4_general_ci
. 그래서 당신이 가진 행이 상상 name="ªßi"
한 후,
select id from users where name='assi';
배열이 utf8mb4_unicode_ci
이면 행을 반환 하지만 배열이로 설정되어 있으면 행을 반환 하지 않습니다utf8mb4_general_ci
.