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?

Author: simhumileco, 2009-04-20

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.

 1703
Author: thomasrutter,
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%.

 177
Author: nightcoder,
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.

 46
Author: Michael Madsen,
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.

 10
Author: Dana the Sane,
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.

 9
Author: simhumileco,
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.

 7
Author: Kamil Kiełczewski,
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 .

 2
Author: Adam,
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/

 0
Author: DavidH,
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