Domanda

Fra utf8_general_ci E utf8_unicode_ci, ci sono differenze in termini di prestazioni?

È stato utile?

Soluzione

Queste due regole di confronto sono sia per la codifica dei caratteri UTF-8. Le differenze sono nel modo in cui il testo è ordinato e confrontato.

Nota: Dal momento che MySQL 5.5.3 si dovrebbe usare utf8mb4 piuttosto che utf8. Entrambi si riferiscono alla codifica UTF-8, ma il più vecchio utf8 aveva una limitazione MySQL-specifico prevenire l'uso di caratteri numerici sopra 0xFFFD.

Le differenze principali

  • utf8mb4_unicode_ci si basa sulle regole ufficiali Unicode per l'ordinamento universale e confronto, che ordina con precisione in una vasta gamma di lingue.

  • utf8mb4_general_ci è un insieme di regole di ordinamento semplificata che mira a fare così come si può mentre prendendo molti scorciatoie progettati per migliorare la velocità. Non segue le regole Unicode e si tradurrà in ordinamento indesiderabili o di confronto in alcune situazioni, come ad esempio quando si utilizzano linguaggi o caratteri particolari.

    Sui server moderni, questo incremento delle prestazioni sarà tutt'altro che trascurabile. E 'stato messo a punto in un momento in cui i server hanno avuto una piccola frazione delle prestazioni della CPU dei computer di oggi.

Nota: esiste ora una versione aggiornata di utf8mb4_unicode_ci chiamato utf8mb4_0900_ai_ci - questo si basa su cambiamenti di Unicode versione 9.0, ed è anche apparentemente più veloce. Adotta un nuovo schema di denominazione per cui 0900 è la versione Unicode e ai significa accento-insensitive -. Come il utf8mb4_unicode_ci precedente, accenti in lettere non sono considerati significativi

Vantaggi di utf8mb4_unicode_ci oltre utf8mb4_general_ci

utf8mb4_unicode_ci, che utilizza le regole di Unicode per l'ordinamento e il confronto, si avvale di un algoritmo piuttosto complesso per il corretto smistamento in una vasta gamma di lingue e quando si utilizza una vasta gamma di caratteri speciali. Queste regole devono tener conto delle convenzioni specifiche della lingua; non tutti ordina loro personaggi in ciò che noi chiameremmo 'ordine alfabetico'.

Per quanto riguarda i latini (cioè "europeo") lingue vanno, non c'è molta differenza tra l'ordinamento Unicode e il utf8mb4_general_ci semplificato l'ordinamento in MySQL, ma ci sono ancora alcune differenze:

  • Per esempio, le regole di confronto tipi Unicode "SS" come "ss", e "OE" come "OE", come le persone che utilizzano quei personaggi normalmente desiderare, mentre utf8mb4_general_ci li ordina come singoli caratteri (presumibilmente come "s "ed "e", rispettivamente).

  • Alcuni caratteri Unicode sono definiti come ignorabile, che significa che non dovrebbe contare verso l'ordinamento e il confronto dovrebbero passare al carattere successivo invece. utf8mb4_unicode_ci gestisce questi correttamente.

Nel lingue non latine, come le lingue asiatiche o le lingue con alfabeti diversi, ci può essere un sacco più differenze tra Unicode l'ordinamento e la selezione utf8mb4_general_ci semplificato. L'idoneità di utf8mb4_general_ci dipenderà in larga misura il linguaggio utilizzato. Per alcune lingue, sarà del tutto insufficiente.

Che cosa si dovrebbe utilizzare?

Non v'è quasi certamente alcun motivo per utilizzare più utf8mb4_general_ci, come abbiamo lasciato alle spalle il punto in cui la velocità della CPU è abbastanza basso che la differenza di prestazioni sarebbe importante. Il database sarà quasi certamente limitato da altri colli di bottiglia di questo.

In passato, alcune persone consiglia di utilizzare utf8mb4_general_ci tranne quando cernita accurata sarebbe stato abbastanza importante da giustificare il costo delle prestazioni. Oggi, che il costo delle prestazioni è quasi scomparsa, e gli sviluppatori stanno trattando l'internazionalizzazione più seriamente.

C'è un argomento da effettuare che se la velocità è più importante per voi che la precisione, si può anche non fare qualsiasi ordinamento a tutti. E 'banale per fare unalgoritmo più veloce se non ne hai bisogno per essere precisi. Quindi, utf8mb4_general_ci è un compromesso che probabilmente non è necessario per ragioni di velocità e, probabilmente, anche non adatto per motivi di precisione.

Un altra cosa io aggiungo è che, anche se si conosce l'applicazione supporta solo la lingua inglese, può ancora bisogno di trattare con i nomi delle persone, che spesso possono contenere caratteri usati in altre lingue in cui è altrettanto importante per ordinare in modo corretto. Utilizzando le regole Unicode per tutto ciò che aiuta aggiungere la pace della mente che la gente Unicode molto intelligenti hanno lavorato molto duramente per rendere l'ordinamento lavoro correttamente.

Che cosa significano le parti

In primo luogo, è ci per -insensitive caso ordinamento e confronto. Questo significa che è adatto per i dati testuali, e comunque non è importante. Gli altri tipi di collazione sono cs (-sensitive) per i dati testuali cui caso è importante, e bin, per cui la codifica deve corrispondere, bit per bit, che è adatto per i campi che sono veramente codificati dati binari (compreso, per esempio, Base64). ordinamento maiuscole e minuscole porta ad alcune strane risultati e confronto tra maiuscole e minuscole può provocare valori duplicati che differiscono solo nel caso in cui la lettera, quindi le regole di confronto case-sensitive stanno cadendo in disgrazia per i dati testuali - se caso è significativo per voi, la punteggiatura allora altrimenti ignorabile e così via è probabilmente significativo, e un confronto binario potrebbe essere più appropriato.

Avanti, unicode o general riferisce alle specifiche regole di ordinamento e confronto - in particolare, il testo modo è normalizzato o confronto. Ci sono molti gruppi diversi di regole per la codifica dei caratteri utf8mb4, con unicode e general essendo due che tentano di funzionare bene in tutte le lingue possibili anziché uno uno specifico. Le differenze tra questi due insiemi di regole sono oggetto di questa risposta. Si noti che nuovi set di regole includono 0900 riferimento a Unicode 9.0 e unicode_520 riferimento a Unicode 5.2.

Infine, utf8mb4 è naturalmente la codifica dei caratteri usata internamente. In questa risposta sto parlando solo di codifiche basate Unicode.

Altri suggerimenti

Volevo sapere qual è la differenza di prestazioni tra l'utilizzo utf8_general_ci e utf8_unicode_ci, ma non ho trovato alcun benchmark elencati su internet, così ho deciso di creare punti di riferimento me stesso.

Ho creato una tabella molto semplice, con 500.000 righe:

CREATE TABLE test(
  ID INT(11) DEFAULT NULL,
  Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;

Poi ho riempito con dati casuali eseguendo la stored procedure:

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

Poi ho creato le seguenti stored procedure per semplice SELECT punto di riferimento, SELECT con LIKE, e l'ordinamento (SELECT con 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;

Nelle procedure memorizzate sopra utf8_general_ci collazione è usato, ma naturalmente durante le prove sono utilizzati sia utf8_general_ci e utf8_unicode_ci.

Ho chiamato ogni procedura immagazzinata 5 volte per ogni confronto (5 volte per utf8_general_ci e 5 volte per utf8_unicode_ci) e quindi calcolato i valori medi.

I miei risultati sono i seguenti:

benchmark_simple_select()

  • con utf8_general_ci: 9.957 ms
  • con utf8_unicode_ci: 10.271 ms

In questo benchmark utilizzando utf8_unicode_ci è più lento di utf8_general_ci del 3,2%.

benchmark_select_like()

  • con utf8_general_ci: 11,441 ms
  • con utf8_unicode_ci: 12.811 ms

In questo benchmark utilizzando utf8_unicode_ci è più lento di utf8_general_ci del 12%.

benchmark_order_by()

  • con utf8_general_ci: 11.944 ms
  • con utf8_unicode_ci: 12.887 ms

In questo benchmark utilizzando utf8_unicode_ci è più lento di utf8_general_ci del 7,9%.

Questo post lo descrive molto bene.

In breve:. Utf8_unicode_ci utilizza le regole Algorithm Unicode come definito negli standard Unicode, che utf8_general_ci è un ordinamento più semplice che si traduce in "meno accurati" smistamento risultati

Vedere il manuale di MySQL, set di caratteri Unicode sezione:

  

Per ogni set di caratteri Unicode,   operazioni eseguite utilizzando la   collazione _general_ci sono più veloci di quelli per la raccolta _unicode_ci.   Ad esempio, i confronti per la   utf8_general_ci collazione sono più veloci,   ma leggermente meno corretto, di   confronti per utf8_unicode_ci. Il   ragione di questo è che   utf8_unicode_ci supporta mappature tali   come espansioni; cioè, quando uno   carattere paragona uguale a   combinazioni di altri personaggi. Per   ad esempio, in tedesco e qualche altro   lingue “ß” è uguale a “ss”.   utf8_unicode_ci supporta anche   contrazioni e personaggi ignorable.   utf8_general_ci è un confronto legacy   che non supporta espansioni,   contrazioni, o caratteri ignorable.   Si può fare solo uno-a-uno   il confronto tra i caratteri.

Quindi, per riassumere, utf_general_ci utilizza un insieme più piccolo e meno corretto (secondo lo standard) di confronti che utf_unicode_ci che dovrebbe implementare l'intera serie. Il set general_ci sarà più veloce perché c'è meno calcolo da fare.

In brevi parole:

Se hai bisogno di un migliore ordinamento, usa utf8_unicode_ci (questo è il metodo preferito),

ma se sei completamente interessato alle prestazioni, usa utf8_general_ci, ma sappi che è un po' datato.

Le differenze in termini di prestazioni sono molto lievi.

Alcuni particolari (PL)

Come possiamo leggere qui ( Peter Gulutzan ) non v'è differenza sull'ordinamento / confrontando lettera polacco "L" (L con corsa - html esc: Ł) ( minuscole: "L" - html esc: ł) - abbiamo seguente ipotesi:

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

In lingua polacca lettera Ł è dopo la lettera L e prima M. Nessuno di questa codifica è meglio o peggio - dipende delle vostre esigenze.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top