Jaka jest różnica między UTF8 general ci a utf8 unicode ci?
Pomiędzy utf8_general_ci
a utf8_unicode_ci
, czy są jakieś różnice w wydajności?
8 answers
Dla tych osób, które nadal pojawiają się na to pytanie w 2020 lub później, istnieją nowsze opcje, które mogą być lepsze niż oba {36]} z nich. Na przykład utf8mb4_0900_ai_ci
.
Wszystkie te zestawienia są dla kodowania znaków UTF-8. Różnice dotyczą sortowania i porównywania tekstu.
_unicode_ci
i _general_ci
to dwa różne zestawy reguł sortowania i porównywania tekstu zgodnie z oczekiwaniami. Nowsze wersje MySQL wprowadzają także nowe zestawy reguł, takie jako _0900_ai_ci
dla równoważnych reguł opartych na Unicode 9.0 - i bez równoważnego wariantu _general_ci
. Osoby czytające to TERAZ powinny prawdopodobnie użyć jednego z tych nowszych zestawień zamiast _unicode_ci
lub _general_ci
. Opis tych starszych zestawień poniżej znajduje się wyłącznie w celach informacyjnych.
MySQL obecnie odchodzi od starszej, wadliwej implementacji UTF-8. Na razie musisz użyć utf8mb4
zamiast utf8
dla części kodowania znaków, aby upewnić się, że otrzymujesz naprawione wersja. Wadliwa wersja pozostaje dla kompatybilności wstecznej, choć jest przestarzała.
Kluczowe różnice
-
utf8mb4_unicode_ci
opiera się na oficjalnych regułach Unicode do uniwersalnego sortowania i porównywania, które sortują dokładnie w wielu językach. -
utf8mb4_general_ci
jest uproszczonym zestawem reguł sortowania, który ma na celu jak najlepiej wykonywać wiele skrótów mających na celu poprawę szybkości. Nie podąża za Unicode reguły i spowoduje niepożądane sortowanie lub porównywanie w niektórych sytuacjach, np. przy użyciu określonych języków lub znaków.Na nowoczesnych serwerach, to zwiększenie wydajności będzie znikome. Został opracowany w czasach, gdy serwery miały niewielki ułamek wydajności procesora dzisiejszych komputerów.
Korzyści z utf8mb4_unicode_ci
ponad utf8mb4_general_ci
utf8mb4_unicode_ci
, który używa reguł Unicode do sortowania i porównywania, wykorzystuje dość złożony algorytm do poprawnego sortowania w szerokim zakresie języków i przy użyciu szerokiej gamy znaków specjalnych. Zasady te muszą uwzględniać konwencje specyficzne dla danego języka; nie każdy sortuje swoje znaki w porządku alfabetycznym.
Jeśli chodzi o języki łacińskie (tj." europejskie"), nie ma dużej różnicy między sortowaniem Unicode a uproszczonym sortowaniem utf8mb4_general_ci
W MySQL, ale nadal istnieje kilka różnic:
-
Na przykład Unicode sortuje " ß " jak "ss", i " Œ " jak " OE " jak ludzie używający tych znaków normalnie chcą, podczas gdy
utf8mb4_general_ci
sortuje je jako pojedyncze znaki (prawdopodobnie jak "S" I " e " odpowiednio). -
Niektóre znaki Unicode są zdefiniowane jako ignorowalne, co oznacza, że nie powinny liczyć się z porządkiem sortowania, a porównanie powinno przejść do następnego znaku.
utf8mb4_unicode_ci
obsługuje je prawidłowo.
W językach niełacińskich, np. azjatyckich języki lub języki z różnymi alfabetami, może być wiele więcej różnic między sortowaniem Unicode a sortowaniem uproszczonym utf8mb4_general_ci
. Przydatność utf8mb4_general_ci
zależy w dużej mierze od używanego języka. Dla niektórych języków, to będzie dość nieodpowiednie.
Czego należy użyć?
Prawie na pewno nie ma już powodu, aby używać utf8mb4_general_ci
, ponieważ zostawiliśmy za sobą punkt, w którym prędkość procesora jest na tyle niska, że różnica w wydajności byłaby ważne. Twoja baza danych będzie prawie na pewno ograniczona przez inne wąskie gardła niż to.
W przeszłości niektórzy ludzie zalecali stosowanie utf8mb4_general_ci
z wyjątkiem sytuacji, gdy dokładne sortowanie miało być wystarczająco ważne, aby uzasadnić koszty wydajności. Dziś ten koszt wydajności zniknął, a deweloperzy traktują internacjonalizację bardziej poważnie.
Jest argument, że jeśli szybkość jest dla Ciebie ważniejsza niż dokładność, możesz równie dobrze nie robić żadnych sortowanie w ogóle. To trywialne, aby algorytm szybciej, jeśli nie trzeba go być dokładnym. Więc utf8mb4_general_ci
jest kompromisem, który prawdopodobnie nie jest potrzebny ze względu na szybkość i prawdopodobnie nie nadaje się również ze względu na dokładność.
Jeszcze jedno, dodam, że nawet jeśli wiesz, że Twoja aplikacja obsługuje tylko język angielski, może nadal trzeba radzić sobie z nazwami ludzi, które często mogą zawierać znaki używane w innych językach, w których równie ważne jest prawidłowe sortowanie. Korzystanie z reguł Unicode dla wszystkiego pomaga dodać spokój, że bardzo inteligentni ludzie Unicode pracowali bardzo ciężko, aby sortowanie działało poprawnie.
Co oznaczają części
Po pierwsze, ci
jest dla sortowanie i porównywanie wielkości liter . Oznacza to, że jest odpowiedni dla danych tekstowych, a wielkość liter nie jest ważna. Inne typy zestawiania to cs
(rozróżnianie wielkości liter) dla danych tekstowych, gdzie wielkość liter jest ważna, oraz bin
, dla których kodowanie musi match, bit za bit, który jest odpowiedni dla pól, które są rzeczywiście zakodowanymi danymi binarnymi (w tym na przykład Base64). Sortowanie z uwzględnieniem wielkości liter prowadzi do dziwnych wyników, a porównanie z wielkościami liter może skutkować podwójnymi wartościami różniącymi się tylko wielkościami liter, więc zestawienia uwzględniające wielkość liter wypadają na korzyść danych tekstowych - jeśli wielkość liter jest dla Ciebie istotna, to w przeciwnym razie ignorowalna interpunkcja itp. jest prawdopodobnie również znacząca, a zestawienie binarne może być bardziej odpowiednie.
Dalej, unicode
lub general
odnosi się do specyficznych reguł sortowania i porównywania - w szczególności sposobu normalizacji lub porównywania tekstu. Istnieje wiele różnych zestawów reguł kodowania znaków utf8mb4, przy czym unicode
i general
są dwoma, które próbują działać dobrze we wszystkich możliwych językach, a nie w jednym konkretnym. Różnice między tymi dwoma zbiorami zasad są przedmiotem niniejszej odpowiedzi. Zauważ, że unicode
używa reguł z Unicode 4.0. Najnowsze wersje MySQL dodaje zestawy reguł unicode_520
używając reguł z Unicode 5.2 i 0900
(zrzucając część "unicode_") używając reguł z Unicode 9.0.
I wreszcie, utf8mb4
jest oczywiście kodowaniem znaków używanym wewnętrznie. W tej odpowiedzi mówię tylko o kodowaniu opartym na Unicode.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-26 23:43:36
Chciałem wiedzieć, jaka jest różnica w wydajności między używaniem utf8_general_ci
i utf8_unicode_ci
, ale nie znalazłem żadnych benchmarków wymienionych w Internecie, więc postanowiłem stworzyć benchmarki samodzielnie.
Stworzyłem bardzo prostą tabelę z 500 000 wierszy:
CREATE TABLE test(
ID INT(11) DEFAULT NULL,
Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
Następnie wypełniłem go losowymi danymi, uruchamiając tę procedurę składowaną:
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
Następnie stworzyłem następujące procedury składowane, aby porównać proste SELECT
, SELECT
z LIKE
, oraz sortowanie (SELECT
z 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;
W procedurach przechowywanych powyżej utf8_general_ci
stosuje się zestawianie, ale oczywiście podczas testów wykorzystałem zarówno utf8_general_ci
, jak i utf8_unicode_ci
.
Wywołałem każdą procedurę składowaną 5 razy dla każdego zestawiania (5 razy dla utf8_general_ci
i 5 razy dla utf8_unicode_ci
), a następnie obliczyłem średnie wartości.
Moje wyniki to:
benchmark_simple_select()
- Z
utf8_general_ci
: 9,957 ms - Z
utf8_unicode_ci
: 10,271 ms
W tym benchmarku używanie {[4] } jest wolniejsze niż utf8_general_ci
o 3,2%.
benchmark_select_like()
- Z
utf8_general_ci
: 11 441 ms - Z
utf8_unicode_ci
: 12,811 ms
W tym benchmarku użycie utf8_unicode_ci
jest wolniejsze niż utf8_general_ci
o 12%.
benchmark_order_by()
- Z
utf8_general_ci
: 11,944 ms - Z
utf8_unicode_ci
: 12,887 ms
W tym benchmarku użycie utf8_unicode_ci
jest wolniejsze niż utf8_general_ci
o 7,9%.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-19 14:51:45
Ten post opisuje to bardzo ładnie.
W skrócie: utf8_unicode_ci
używa algorytmu sortowania Unicode zdefiniowanego w standardach Unicode, podczas gdy utf8_general_ci
jest prostszym porządkiem sortowania, co skutkuje "mniej dokładnymi" wynikami sortowania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-13 08:47:02
Zobacz instrukcję mysql, Unicode Character Sets Sekcja:
Dla dowolnego zestawu znaków Unicode, operacje wykonywane przy użyciu _general_ci są szybsze niż te dla _unicode_ci. Na przykład porównania dla utf8_general_ci są szybsze, ale nieco mniej poprawne, niż porównania dla utf8_unicode_ci. Na powodem tego jest to, że utf8_unicode_ci obsługuje mapowania takie jako ekspansje; to znaczy, gdy jeden charakter porównuje jako równe kombinacje innych znaków. Na przykład po niemiecku i kilka innych języki " ß "są równe"ss". utf8_unicode_ci obsługuje również skurcze i nieświadome postacie. utf8_general_ci jest zbiorem dziedzicznym nie obsługuje rozszerzeń, skurcze, czyli ignorowane postacie. Może zrobić tylko jeden do jednego porównania między postaciami.
Podsumowując, utf_general_ci używa mniejszego i mniej poprawnego (zgodnie ze standardem) zestawu porównań niż utf_unicode_ci, które powinny implementować cały standard. Zestaw general_ci będzie szybszy, ponieważ jest mniej obliczeń do wykonania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-20 04:09:58
W krótkich słowach:
Jeśli potrzebujesz lepszej kolejności sortowania-użyj utf8_unicode_ci
(jest to preferowana metoda),
Ale jeśli jesteś całkowicie zainteresowany wydajnością-użyj utf8_general_ci
, ale wiedz, że jest to trochę przestarzałe.
Różnice w wydajności są bardzo niewielkie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 08:51:49
Niektóre szczegóły (PL)
Jak możemy przeczytać tutaj (Peter Gulutzan) jest różnica w sortowaniu / porównywaniu polskiej litery " Ł "(L z pociągnięciem-html esc: Ł
) (małe litery: "ł" - html esc: ł
) - Mamy następujące założenie:
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
W języku polskim litera Ł
jest po literze L
, A przed M
. Nikt z tego kodowania nie jest lepszy ani gorszy-to zależy od twoich potrzeb.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-20 08:00:37
Istnieją dwie duże różnice w sortowaniu i dopasowaniu znaków:
Sortowanie :
-
utf8mb4_general_ci
usuwa wszystkie akcenty i sortuje jeden po drugim, co może powodować nieprawidłowe wyniki sortowania. -
utf8mb4_unicode_ci
sortuje dokładnie.
Dopasowanie Znaków
Różnie dopasowują postacie.
Na przykład w utf8mb4_unicode_ci
Masz i != ı
, ale w utf8mb4_general_ci
posiada ı=i
.
Na przykład wyobraź sobie, że masz wiersz z name="Yılmaz"
. Wtedy
select id from users where name='Yilmaz';
Zwróci wiersz, jeśli kolokacja jest utf8mb4_general_ci
, ale jeśli jest kolokowana z utf8mb4_unicode_ci
, to nie zwróci wiersz!
Z drugiej strony mamy to a=ª
i ß=ss
W utf8mb4_unicode_ci
, co nie ma miejsca w utf8mb4_general_ci
. Więc wyobraź sobie, że masz rząd z name="ªßi"
, a następnie
select id from users where name='assi';
Zwróci wiersz, jeśli kolokacja jest utf8mb4_unicode_ci
, ale nie zwróci wiersz, jeśli kolokacja jest ustawiona na utf8mb4_general_ci
.
Pełna lista dopasowań dla każdej kolokacji może być znaleziono tutaj .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-06 18:31:40
Zgodnie z tym postem, istnieje znacznie duża korzyść wydajności MySQL 5.7 przy użyciu utf8mb4_general_ci zamiast utf8mb4_unicode_ci: https://www.percona.com/blog/2019/02/27/charset-and-collation-settings-impact-on-mysql-performance/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-22 23:59:17