UTF-8: ¿General? ¿Compartimiento? Unicode?

279

Estoy tratando de averiguar qué cotejo debería usar para varios tipos de datos. El 100% del contenido que almacenaré es enviado por el usuario.

Tengo entendido que debería usar UTF-8 General CI (mayúsculas y minúsculas) en lugar de UTF-8 Binary. Sin embargo, no puedo encontrar una distinción clara entre UTF-8 General CI y UTF-8 Unicode CI.

  1. ¿Debo almacenar contenido enviado por el usuario en columnas UTF-8 General o UTF-8 Unicode CI?
  2. ¿A qué tipo de datos se aplicaría UTF-8 Binary?
Dolph
fuente
16
Nota al margen, pero en lugar de utf8, utf8mb4úsela para obtener soporte completo para UTF-8. Comentando aquí porque las respuestas a esta pregunta popular no abordan esto. mathiasbynens.be/notes/mysql-utf8mb4
Steven R. Loomis
Si desea plegar la caja, pero la sensibilidad del acento, presente una solicitud en bugs.mysql.com .
Rick James
O haga clic en "Me afecta" en bugs.mysql.com/bug.php?id=58797 y agregue un comentario.
Rick James

Respuestas:

299

En general, utf8_general_ci es más rápido que utf8_unicode_ci , pero menos correcto.

Aquí está la diferencia:

Para cualquier conjunto de caracteres Unicode, las operaciones realizadas utilizando la clasificación _general_ci son más rápidas que las de la clasificación _unicode_ci . Por ejemplo, las comparaciones para la intercalación utf8_general_ci son más rápidas, pero un poco menos correctas, que las comparaciones para utf8_unicode_ci. La razón de esto es que utf8_unicode_ci admite mapeos como expansiones; es decir, cuando un personaje se compara como igual a combinaciones de otros personajes. Por ejemplo, en alemán y algunos otros idiomas "ß" es igual a "ss". utf8_unicode_ci también admite contracciones y caracteres ignorables. utf8_general_ci es una recopilación heredada que no admite expansiones, contracciones o caracteres ignorables. Solo puede hacer comparaciones uno a uno entre los personajes.

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

Para obtener una explicación más detallada, lea la siguiente publicación de los foros de MySQL: http://forums.mysql.com/read.php?103,187048,188748

En cuanto a utf8_bin: utf8_general_ci y utf8_unicode_ci realizan una comparación que no distingue entre mayúsculas y minúsculas. En contraste, utf8_bin distingue entre mayúsculas y minúsculas (entre otras diferencias), ya que compara los valores binarios de los caracteres.

Sagi
fuente
2
Creo que si no tiene una buena razón para usar _unicode_ci, use _general_ci.
Sagi
44
Sin embargo, esto realmente no responde a la pregunta en profundidad. ¿Cuál es la diferencia entre estas colaciones exactamente?
Pekka
44
Tiene razón, la diferencia exacta no se proporciona aquí por simplicidad. He agregado un enlace a una publicación con la diferencia exacta .
Sagi
NB le show collation;permite ver la clasificación predeterminada para cada conjunto de caracteres. 5.1 muestra utf8_general_cicomo predeterminado para utf8.
David Carboni
9
¿Hay algún recurso que profundice más en la diferencia de velocidad real entre las dos intercalaciones? ¿Estamos hablando de una caída del 0.1% en el rendimiento o una caída del 10%?
Emphram Stavanger
90

También debe tener en cuenta el hecho de que con utf8_general_ci al usar un campo varchar como índice único o primario, insertar 2 valores como 'a' y 'á' daría un error de clave duplicado.

Alex Hepp
fuente
3
Gracias, esto es útil para evitar nombres de usuario similares (por ejemplo, si "jose" existe, no quisiera que otra persona creara un usuario "josé") NB: esto también es válido para la mayoría de las intercalaciones utf8 (excepto utf8_bin). El más seguro / seguro / más completo esutf8_unicode_ci
Costa
2
Uso utf8_bin donde quiero que jose y josé se distingan en el índice. Por ejemplo, una columna que registra las operaciones de búsqueda / reemplazo, donde el usuario podría haber decidido buscar josé y reemplazarlo por jose. (Estoy escribiendo un programa de hoja de cálculo)
Buttle Butkus
33
  • utf8_bincompara los bits a ciegas. Sin plegado de la caja, sin pelado.
  • utf8_general_cicompara un byte con un byte. Hace plegado de mayúsculas y minúsculas , pero no hay comparaciones de 2 caracteres: ijno es igual ijen esta colación.
  • utf8_*_cies un conjunto de reglas específicas del idioma, pero por lo demás me gusta unicode_ci. Algunos casos especiales: Ç, Č, ch,ll
  • utf8_unicode_cisigue un antiguo estándar Unicode para las comparaciones. ij= ij, pero ae! =æ
  • utf8_unicode_520_cisigue un nuevo estándar Unicode. ae=æ

Consulte la tabla de colación para obtener detalles sobre qué es igual a qué en varias colaciones utf8.

utf8, tal como lo define MySQL, está limitado a los códigos utf8 de 1 a 3 bytes. Esto deja fuera a Emoji y algunos chinos. Por lo tanto, debería cambiarse utf8mb4si quiere ir mucho más allá de Europa.

Los puntos anteriores se aplican a utf8mb4, después de un cambio de ortografía adecuado. En adelante, utf8mb4y utf8mb4_unicode_520_cison preferidos.

  • utf16 y utf32 son variantes en utf8; prácticamente no les sirve de nada.
  • ucs2 está más cerca de "Unicode" que de "utf8"; prácticamente no tiene uso para ello.
Rick James
fuente
1
Re "estad atentos": las colaciones 8.0 muestran cómo varios personajes, diptongos, etc., se comparan en las colaciones 8.0 utf8mb4; utf8 es casi lo mismo.
Rick James
Y las intercalaciones de 8.0 tienen una velocidad significativamente mayor que 5.x.
Rick James
Sería bueno si esa página incluye utf8mb4_bin en la parte superior. Sé que no coincide en absoluto con los personajes, pero es bueno para los novatos.
Henk Poley
6

Realmente, probé guardando valores como 'é' y 'e' en la columna con índice único y causan errores duplicados en 'utf8_unicode_ci' y 'utf8_general_ci'. Puede guardarlos solo en la columna intercalada 'utf8_bin'.

Y los documentos de mysql (en http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html ) sugieren en su conjunto de ejemplos la recopilación 'utf8_general_ci'.

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
vitalii
fuente
1
Hice una prueba rápida sobre esto, y parece ser precisa. Ambas colaciones se comportan igual cuando se trata de una clave única en una columna y valores con tildes y similares.
MirroredFate
@MirroredFate OK, debo agregar allí que la columna debe tener un índice único para causar este error. Implica en mi respuesta.
vitalii 01 de
3

La respuesta aceptada está desactualizada.

Si usa MySQL 5.5.3+, use en utf8mb4_unicode_cilugar de utf8_unicode_cipara asegurarse de que los caracteres escritos por sus usuarios no le darán errores.

utf8mb4admite emojis, por ejemplo, mientras que utf8podría darte cientos de errores relacionados con la codificación como:

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

Marwann
fuente
Esta respuesta (correctamente) aborda problemas con la codificación de Emoji (y algunos de chino). Pero la pregunta parece centrarse en la recopilación. utf8mb4_unicode_citrata (creo) todos los Emoji como iguales. utf8mb4_unicode_520_cida una orden a Emoji.
Rick James