UTF-8: Generale? Bidone? Unicode?


279

Sto cercando di capire quale raccolta dovrei usare per vari tipi di dati. Il 100% del contenuto che memorizzerò viene inviato dall'utente.

La mia comprensione è che dovrei usare la CI generale UTF-8 (senza distinzione tra maiuscole e minuscole) invece della binaria UTF-8. Tuttavia, non riesco a trovare una chiara distinzione tra CI generale UTF-8 e CI Unicode UTF-8.

  1. Devo archiviare il contenuto inviato dall'utente nelle colonne UTF-8 General o UTF-8 Unicode CI?
  2. A quale tipo di dati sarebbe applicabile UTF-8 Binary?

16
Nota a margine ma invece di utf8, utilizzare utf8mb4invece per il pieno supporto UTF-8. Commentando qui perché le risposte a questa domanda popolare non affrontano questo. mathiasbynens.be/notes/mysql-utf8mb4
Steven R. Loomis

Se si desidera piegare la custodia, ma la sensibilità dell'accento, si prega di presentare una richiesta a bugs.mysql.com .
Rick James,

Oppure fai clic su "Mi interessa" su bugs.mysql.com/bug.php?id=58797 e aggiungi un commento.
Rick James,

Risposte:


299

In generale, utf8_general_ci è più veloce di utf8_unicode_ci , ma meno corretto.

Ecco la differenza:

Per qualsiasi set di caratteri Unicode, le operazioni eseguite utilizzando le regole di confronto _general_ci sono più veloci di quelle per le regole di confronto _unicode_ci . Ad esempio, i confronti per la collazione utf8_general_ci sono più veloci, ma leggermente meno corretti, rispetto ai confronti per utf8_unicode_ci. La ragione di ciò è che utf8_unicode_ci supporta mappature come espansioni; cioè, quando un personaggio si confronta come uguale alle combinazioni di altri personaggi. Ad esempio, in tedesco e in altre lingue "ß" è uguale a "ss". utf8_unicode_ci supporta anche contrazioni e personaggi ignorabili. utf8_general_ci è una raccolta legacy che non supporta espansioni, contrazioni o personaggi ignorabili. Può fare solo confronti uno a uno tra i personaggi.

Citato da: http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

Per una spiegazione più dettagliata, leggere il seguente post dai forum MySQL: http://forums.mysql.com/read.php?103,187048,188748

Per quanto riguarda utf8_bin: sia utf8_general_ci che utf8_unicode_ci eseguono un confronto senza distinzione tra maiuscole e minuscole. In constrast , utf8_bin fa distinzione tra maiuscole e minuscole (tra le altre differenze), perché confronta i valori binari dei caratteri.


2
Penso che se non hai una buona ragione per usare _unicode_ci, allora usa _general_ci.
Sagi,

4
Questo non risponde davvero alla domanda in profondità però. Qual è esattamente la differenza tra queste regole di confronto?
Pekka,

4
Hai ragione, la differenza esatta non è fornita qui per motivi di semplicità. Ho aggiunto un link a un post con la differenza esatta .
Sagi,

NB show collation;consente di visualizzare le regole di confronto predefinite per ciascun set di caratteri. 5.1 mostra utf8_general_cicome predefinito per utf8.
David Carboni,

9
Ci sono risorse che andrebbero più in profondità nella differenza di velocità effettiva tra le due regole di confronto? Stiamo parlando di un calo dello 0,1% delle prestazioni o di un calo del 10%?
Emphram Stavanger

90

Dovresti anche essere consapevole del fatto che con utf8_general_ci quando si utilizza un campo varchar come indice univoco o primario inserendo 2 valori come 'a' e 'á' si darebbe un errore chiave duplicato.


3
Grazie, questo è utile per evitare nomi utente simili (ad esempio, se esiste "jose", non vorrei che qualcun altro creasse un utente "josé") NB: questo vale anche per la maggior parte delle raccolte utf8 (tranne utf8_bin). Il più sicuro / più sicuro / più completo èutf8_unicode_ci
Costa

2
Uso utf8_bin dove voglio che jose e josé siano distinti nell'indice. Ad esempio, una colonna che registra le operazioni di ricerca / sostituzione, in cui l'utente potrebbe aver deciso di cercare josé e sostituirlo con jose. (Sto scrivendo un programma per fogli di calcolo)
Buttle Butkus,

33
  • utf8_binconfronta i bit alla cieca. Nessuna custodia pieghevole, nessun accento di stripping.
  • utf8_general_ciconfronta un byte con un byte. Fa piegare le maiuscole e mettere a nudo l'accento, ma non ci sono confronti di 2 caratteri: ijnon è uguale ijin questo confronto.
  • utf8_*_ciè un insieme di regole specifiche della lingua, ma altrimenti gradisce unicode_ci. Alcuni casi particolari: Ç, Č, ch,ll
  • utf8_unicode_cisegue un vecchio standard Unicode per i confronti. ij= ij, ma ae! =æ
  • utf8_unicode_520_cisegue un nuovo standard Unicode. ae=æ

Vedi la tabella delle regole di confronto per dettagli su ciò che è uguale a ciò che in varie regole di confronto utf8.

utf8, come definito da MySQL è limitato ai codici utf8 da 1 a 3 byte. Questo esclude Emoji e alcuni cinesi. Quindi dovresti davvero passare a utf8mb4se vuoi andare molto oltre l'Europa.

I punti precedenti si applicano a utf8mb4, dopo un'adeguata modifica ortografica. Andando avanti, utf8mb4e utf8mb4_unicode_520_cisono preferiti.

  • utf16 e utf32 sono varianti su utf8; non serve praticamente a loro.
  • ucs2 è più vicino a "Unicode" di "utf8"; praticamente non serve a niente.

1
Ri "rimanete sintonizzati": le regole di confronto 8.0 mostrano come vari personaggi, dittonghi, ecc. Si confrontano nelle regole di confronto 8.0 utf8mb4; utf8 è principalmente lo stesso.
Rick James,

E le regole di confronto 8.0 sono significativamente più veloci di 5.x.
Rick James,

sarebbe bello se quella pagina elenca utf8mb4_bin in alto. So che non corrisponde affatto al personaggio, ma è buono per i neofiti.
Henk Poley,

6

In realtà, ho testato il salvataggio di valori come 'é' ed 'e' in colonna con un indice univoco e causano errori duplicati su 'utf8_unicode_ci' e 'utf8_general_ci'. Puoi salvarli solo nella colonna fascicolata 'utf8_bin'.

E i documenti mysql (in http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html ) suggeriscono nei suoi esempi di impostare la raccolta 'utf8_general_ci'.

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

1
Ho fatto un rapido test su questo, e sembra essere accurato. Entrambe le regole di confronto si comportano allo stesso modo quando si tratta di una chiave univoca su una colonna e di valori con tilde e simili.
MirroredFate

@MirroredFate OK, dovrei aggiungere lì che la colonna dovrebbe avere un indice univoco per causare questo errore. Implica nella mia risposta.
vitalii,

3

La risposta accettata è obsoleta.

Se usi MySQL 5.5.3+, usa utf8mb4_unicode_ciinvece di utf8_unicode_ciper assicurarti che i caratteri digitati dai tuoi utenti non ti daranno errori.

utf8mb4supporta ad esempio gli emoji, mentre utf8potrebbe darti centinaia di bug relativi alla codifica come:

Incorrect string value: ‘\xF0\x9F\x98\x81…’ for column ‘data’ at row 1


Questa risposta (corretta) risolve i problemi con la codifica di Emoji (e alcuni dei cinesi). Ma la domanda sembra concentrarsi sulla collazione. utf8mb4_unicode_ciconsidera (penso) tutte le Emoji uguali. utf8mb4_unicode_520_cidà un ordine a Emoji.
Rick James,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.