Între utf8_general_ci " și " utf8_unicode_ci
, există diferențe în termeni de performanță?
Aceste două colaționări sunt atât pentru UTF-8 codificare a caracterelor. Diferențele sunt în modul în care textul este sortat și comparate.
Notă: trebuie să utilizați utf8mb4
mai degrabă decât utf8
. Ambele se referă la codificarea UTF-8, dar mai în vârstă utf8
a avut un MySQL specifice pentru limitarea și prevenirea consumului de caractere numerotate mai sus 0xFFFD.
Notă: cele mai Noi versiuni de MySQL-au actualizat Unicode reguli de sortare, disponibil sub nume precum `utf8mb4_0900_ci pentru reguli bazate pe Unicode 9.0 - și fără echivalent "general" de variantă.
Diferențe cheie
utf8mb4_unicode_ci
este bazat pe oficial Unicode reguli universale de sortare și de comparație, care felul precis într-o gamă largă de limbi. utf8mb4_general_ci
este un set simplificat de reguli de sortare care are scopul de a face la fel de bine ca el poate în timp ce lua multe scurtături conceput pentru a îmbunătăți viteza. Nu urmați Unicode reguli și va duce la nedorite de sortare sau comparație, în unele situații, cum ar fi atunci când se utilizează anumite limbi sau caractere.
Moderne de servere, acest impuls de performanță va fi neglijabil. Acesta a fost conceput într-un moment când serverele avut o mică fracțiune de performanțele PROCESORULUI de azi's calculatoare.
Notă: există acum o versiune actualizată a utf8mb4_unicode_ci "numit" utf8mb4_0900_ai_ci
- aceasta se bazează pe modificări în Unicode versiunea 9.0, și este, de asemenea, se pare că mai repede. Se adoptă un nou sistem de numire prin care 0900
este versiunea Unicode și " ai " înseamnă accent-insensibil - ca anterior utf8mb4_unicode_ci
, accente în scrisori nu sunt considerate semnificative.
Beneficii de utf8mb4_unicode_ci "peste" utf8mb4_general_ci`
utf8mb4_unicode_ci
, care utilizează Unicode reguli pentru sortarea și comparație, are un algoritm destul de complex pentru sortare corectă într-o gamă largă de limbi și atunci când se utilizează o gamă largă de caractere speciale. Aceste reguli trebuie să ia în considerare specifice limbii convenții; nu toată lumea felul personajele lor în ceea ce numim 'ordine alfabetică'.
În măsura în latină (de exemplu, "European") limbi du-te, nu există o diferență mare între Unicode sortare și simplificat utf8mb4_general_ci
sortare în MySQL, dar încă mai există câteva diferențe: utf8mb4_general_ci
felul ei ca personaje unice (probabil ca "s" și "e" respectiv). utf8mb4_unicode_ci
se ocupă de acestea în mod corespunzător.
În limbile non-latine, cum ar fi limbi Asiatice sau limbile cu alfabete diferite, pot exista o mulțime mai mult diferențe între Unicode sortare și simplificat utf8mb4_general_ci
sortare. Adecvarea utf8mb4_general_ci
va depinde foarte mult de limbajul folosit. Pentru unele limbi,'ll fi destul de inadecvate.
Ce ar trebui să utilizați?
Nu există aproape niciun motiv pentru a folosi utf8mb4_general_ci mai, așa cum am lăsat în urmă la punctul în care viteza PROCESORULUI este suficient de scăzută pentru ca diferenta de performanta ar fi important. Baza de date va fi aproape sigur limitată de alte blocaje decât aceasta.
În trecut, unii oameni se recomandă să utilizați utf8mb4_general_ci
cu excepția cazului când corecte de sortare a fost de gând să fie suficient de important pentru a justifica costul de performanță. Astăzi, ca performanta costa a dispărut, iar dezvoltatorii sunt tratarea internaționalizare mult mai serios.
Nu's un argument care să fi făcut asta dacă viteza este mai importantă decât acuratețea, ar fi bine să nu faci nici o sortare la toate. L's banal de a face un algoritm mai rapid dacă nu aveți nevoie de ea să fie corecte. Deci, utf8mb4_general_ci
este un compromis pe care's, probabil, nu este necesar din motive de viteză și, probabil, de asemenea, nu este potrivit pentru exactitatea motive.
Un alt lucru pe care am'll a adăuga este că, chiar dacă știi aplicație acceptă numai limba engleză, ar putea încă mai trebuie să se ocupe cu oamenii's nume, care de multe ori poate conține caractere utilizate în alte limbi în care este la fel de important pentru a sorta corect. Folosind Unicode reguli pentru tot ceea ce ajută adăuga pacea de la minte că foarte inteligent Unicode oameni au lucrat din greu pentru a face sortarea funcționeze corect.
Ce părți să spun
În primul rând, " ci " este pentru majuscule sortarea și comparație. Acest lucru înseamnă că's potrivit pentru date de tip text, și cazul nu este important. Alte tipuri de colaționare sunt cs
(case-sensitive) pentru date de tip text în cazul în care caz este important, și "interval", de unde codificarea trebuie să se potrivească, pic de biți, care este potrivit pentru domenii care sunt codificate binar de date (inclusiv, de exemplu, Base64). Case-sensitive sortare duce la unele rezultate ciudate și case-sensitive comparație pot rezulta în valori duplicate diferă numai în caz scrisoare, atât de sensibil la caz colaționări sunt care se încadrează afară de favoare pentru date de tip text - dacă cazul este important pentru tine, atunci altfel banale semne de punctuație și așa mai departe este, probabil, de asemenea, semnificativă, și un binar colaționare ar putea fi mai adecvat.
Apoi, unicode
sau "general" se referă la cele specifice de sortare și compararea normelor - în special, modul în text este normalizat sau comparativ. Există mai multe seturi diferite de reguli pentru utf8mb4 de codare a caracterelor, cu unicode
și "general" de a fi doi, care încearcă să lucreze bine în toate limbile posibile, mai degrabă decât unul specific. Diferențele dintre aceste două seturi de norme sunt subiectul acestui răspuns. Rețineți că unicode
utilizează reguli de Unicode 4.0. Recente versiuni de MySQL adauga regulilor unicode_520
folosind regulile de la Unicode 5.2, și 0900
(cădere "unicode_" parte) folosind regulile de la Unicode 9.0.
Și în cele din urmă, utf8mb4` este, desigur, codificarea caracterelor utilizate pe plan intern. În acest răspuns am'm vorbesc numai despre bazate pe Unicode codare.Am vrut să știu ce este diferența de performanță între utilizarea utf8_general_ci " și " utf8_unicode_ci
, dar nu am gasit nici o referință enumerate pe internet, așa că am decis pentru a crea repere mine.
Am creat un tabel foarte simplu, cu 500.000 de rânduri:
CREATE TABLE test(
ID INT(11) DEFAULT NULL,
Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
Apoi l-am umplut cu date aleatoare prin rularea această procedură stocată:
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
Apoi am creat următoarele proceduri stocate pentru referință simplu "ALEGE", "ALEGE" cu "CA", și de sortare ("ALEGE" cu "ORDINUL PRIN"):
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;
În proceduri stocate de mai sus utf8_general_ci
colaționare este folosit, dar, desigur, în timpul testelor am folosit ambele utf8_general_ci " și " utf8_unicode_ci
.
Am sunat la fiecare procedură stocată de 5 ori pentru fiecare colaționare (de 5 ori pentru utf8_general_ci și de 5 ori pentru utf8_unicode_ci`) și apoi se calculează valorile medii.
Rezultatele mele sunt:
benchmark_simple_select()
utf8_general_ci
: 9,957 ms utf8_unicode_ci
: 10,271 ms În acest produs de referință, folosind utf8_unicode_ci
este mai lent decât utf8_general_ci
de 3.2%.
benchmark_select_like()
utf8_general_ci
: 11,441 ms utf8_unicode_ci
: 12,811 ms În acest produs de referință, folosind utf8_unicode_ci
este mai lent decât utf8_general_ci
de 12%.
benchmark_order_by()
utf8_general_ci
: 11,944 ms utf8_unicode_ci
: 12,887 ms În acest produs de referință, folosind utf8_unicode_ci
este mai lent decât utf8_general_ci
cu 7,9%.
Acest post descrie foarte frumos.
Pe scurt: utf8_unicode_ci folosește Unicode Colaționare Algoritm astfel cum sunt definite în Unicode standarde, întrucât utf8_general_ci este mai simplă ordine de sortare care duce la "mai puțin precise" sortare rezultate.
Vezi mysql manual, Seturi de Caractere Unicode secțiune:
Pentru orice set de caractere Unicode, operațiile efectuate cu ajutorul _general_ci colaționare sunt mai rapide decât cele pentru _unicode_ci colaționare. De exemplu, comparații pentru utf8_general_ci colaționare sunt mai rapide, dar mai puțin corecte, decât comparații pentru utf8_unicode_ci. La motivul pentru aceasta este că utf8_unicode_ci sprijină astfel de operatori ca extinderi; că este, atunci când o caracter compară ca fiind egală cu combinații de alte personaje. Pentru de exemplu, în germană și alte limbi "ß" este egal cu "ss". utf8_unicode_ci susține, de asemenea, contracții și banale caractere. utf8_general_ci este o moștenire de colaționare care nu are suport pentru extinderi, contractii, sau personaje banale. Se poate face numai unu-la-unu comparații între personaje.
Deci, pentru a rezuma, utf_general_ci folosește mai mici și mai puțin corectă (conform standard) set de comparații decât utf_unicode_ci care trebuie să pună în aplicare întregul standard. La general_ci set va fi mai rapid, deoarece există mai puțin de calcul a face.
În cuvinte scurte:
Dacă aveți nevoie de mai bine de sortare pentru utilizare utf8_unicode_ci
(aceasta este metoda preferată),
dar dacă ai extrem de interesați de performanță - utilizarea `utf8_general_ci, dar știu că este un pic depășite.
Diferențele în termeni de performanță sunt foarte mici.
După cum putem citi aici (Peter Gulutzan) există o diferență privind sortarea/compararea poloneză scrisoare "Ł" (L cu accident vascular cerebral - html esc: Ł
) (cu litere mici: "ł" - html esc: ł
) avem următoarea presupunere:
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
În limba poloneză scrisoare Ł
este după litera " L "și înainte de "M". Nici unul din această codificare este mai bine sau mai rău - depinde de nevoile dumneavoastra.
În conformitate cu acest post, există un considerabil de mare performanță beneficia pe MySQL 5.7 atunci când se utilizează utf8mb4_general_ci în loc de utf8mb4_unicode_ci: https://www.percona.com/blog/2019/02/27/charset-and-collation-settings-impact-on-mysql-performance/