¿Debería usarse Latin-1 sobre UTF-8 cuando se trata de la configuración de la base de datos?

65

Estamos utilizando MySQL en la empresa para la que trabajo, y creamos aplicaciones internas y orientadas al cliente utilizando Ruby on Rails.

Cuando comencé a trabajar aquí, me encontré con un problema que nunca había encontrado antes; la base de datos en el servidor de producción está establecida en Latin-1, lo que significa que la gema MySQL arroja una excepción cada vez que hay una entrada del usuario donde el usuario copia y pega caracteres UTF-8.

Mi jefe llama a estos "personajes malos", ya que la mayoría de ellos son caracteres no imprimibles, y dice que debemos eliminarlos. He encontrado algunas formas de hacer esto, pero finalmente hemos terminado en una circunstancia en la que se necesitaba un personaje UTF-8. Además, es un poco complicado, especialmente porque parece que la única solución sobre la que he leído para este problema es configurar la base de datos en UTF-8 (tiene sentido para mí).

El único argumento que he escuchado para seguir con Latin-1 es que permitir caracteres UTF-8 no imprimibles puede estropear las búsquedas de texto / texto completo en MySQL. ¿Es esto realmente cierto?

¿Hay otras razones por las que uno debería usar Latin-1 sobre UTF-8? Tengo entendido que es superior y se está volviendo más omnipresente.

Ravenstine
fuente
44
@jon LATIN-1 no es específico del inglés. El español está perfectamente contenido allí, así como el francés si no me equivoco.
Darkhogg
44
@Darkhog: Latin1 no es específico para el inglés, pero está esencialmente restringido a los alfabetos de Europa occidental.
Bart van Ingen Schenau
16
El único beneficio posible de usar Latin 1 en lugar de UTF-8 en un sistema moderno es el sabotaje. Eso, por supuesto, es solo un beneficio para el saboteador, y para quienes sean sus lealtades, no para los propietarios o desarrolladores del sistema.
Jon Hanna
13
Lástima que su base de datos no pueda contener el símbolo del Euro, o incluso mi nombre (דותן).
dotancohen 01 de
20
usuario "copia y pega" caracteres no latin-1? no trates a Unicode como algo frívolo irrelevante que solo les importa a los nerds traviesos. muchos de nosotros escribimos caracteres que no caben en latin-1 de forma regular; escucho que mucha gente habla idiomas no europeos, incluso ♥
Eevee

Respuestas:

130

Unicode es ciertamente difícil, y la codificación UTF-8 tiene un par de propiedades inconvenientes. Sin embargo, UTF-8 se ha convertido en la codificación estándar de facto en la web, superando a ASCII, Latin-1, UCS-2 y UTF-16. Simplemente use UTF-8 en todas partes .

La razón más importante por la que debe admitir Unicode es que no debe hacer suposiciones innecesarias sobre la entrada del usuario. No tengo idea de cuál es su dominio, pero cosas como nombres de usuario hebreos, una publicación de blog sobre China, un comentario con Emoji, o simplemente texto bien diseñado, como "esto", deberían ser posibles ... Oh, esas eran comillas tipográficamente correctas ( “”en lugar de ""), guiones en todo el ancho y puntos suspensivos, que son caracteres que son comunes en el texto en inglés, pero que no son compatibles con ASCII o Latin-1. Por lo tanto, no admitir otros scripts no es solo una gran mierda para otras culturas, pero apegarse al latín-1 ni siquiera te permite escribir un inglés adecuado.

La idea de que Unicode solo permite "caracteres malos" es incorrecta. Sí, el texto es realmente complicado y Unicode no te lo ocultará. Su jefe puede estar pensando en caracteres compuestos, donde un punto de código base, tal como aes modificado por puntos de código posteriores que, por ejemplo, representan signos diacríticos para formar un carácter visual tal como á. Esto realmente no se interpone en tu camino cuando intentas hacer búsquedas si haces algún tipo de normalización. Por ejemplo, podría almacenar todo el texto en el formulario NFC que contrae dichas composiciones en su forma precompuesta si hay una disponible. Al realizar la búsqueda, también puede eliminar todos los caracteres que componen el texto, pero esto puede cambiar sustancialmente su significado en algunos idiomas.

Unicode también agrega muchos caracteres no imprimibles, pero incluso ASCII tiene muchos de ellos. ¿Manejarás un NUL en medio de una cuerda? ¿Qué tal 0x1C, un "separador de archivos"? Nunca he visto la mitad de esos . Latin-1 agrega un guión suave que indica oportunidades de salto de palabras, pero por lo demás es invisible. ¿Eso también interrumpe tu búsqueda de texto completo? En otras palabras, ¡incluso ASCII y Latin-1 le permiten romper completamente su entrada si supone que todo es solo texto imprimible!

amon
fuente
8
Desde la perspectiva de la base de datos, algunos de esos caracteres no están / no deberían permitirse en un campo de tipo de texto (text / varchar / char / etc.). MySQL no permite caracteres nulos en estos tipos de datos, pero otras bases de datos como PostgreSQL no lo hacen. Se supone que debe usar BLOB (MySQL) o BYTEA (PostgreSQL) si desea poder almacenar dichos caracteres.
cimmanon
15
"apegarse al latín-1 ni siquiera te permite escribir un inglés adecuado" Eso es algo bueno, de lo contrario, unicode se resistiría aún más. ;-)
Deduplicador
3
@ PaŭloEbermann Los caracteres NUL integrados significan que sus datos son un blob binario, no solo una cadena. NULs fue un extraño ejemplo, ya que creo que UTF-8 evita usar un \0byte como parte de una codificación de varios bytes, para asegurarse de que el código que no sea UTF8 no se detenga en el medio de una cadena.
Peter Cordes
77
Todos los caracteres Unicode se pueden imprimir: solo necesita la fuente correcta :-)
James Anderson
44
@JamesAnderson la fuente estaría mal y rota. en.wikipedia.org/wiki/Unicode_control_characters
djechlin
62

Creo que más allá de la cuestión técnica, su jefe puede no tener el tiempo para mantenerse al día con los estándares actuales.

Dado que su postura no está completamente fuera del almuerzo, solo está desactualizada, respete su posición cuando discuta este asunto (y debe recordar discutir , no discutir) e intente resolver las preocupaciones que tiene con respecto a UTF-8. Sospecho que el problema subyacente no es un problema técnico y puede requerir cierto nivel de negociación de habilidades blandas.

Nelson
fuente
66
No podría aprobar más. En realidad, lamento que en mi propia respuesta pasé por alto completamente el "lado humano", que en este tema podría ser primordial. Ojalá pudiera votar más de una vez :-)
LSerni
2
llamando a todo lo que está fuera de latin-1 bad charactery pensando que esto non-printablees just out-datedpara ti?
njzk2
2
El verdadero problema es: "¿Es un problema técnico con el que estamos lidiando?" No creo que el jefe del OP fuera a la escuela y le enseñaron esto, o leí algún manual técnico / diario y llegué a esa conclusión. No tengo la sensación de que la solución sea estrictamente técnica. Irónicamente, el comentario muestra exactamente el corazón del problema; abordar este problema puede ser extremadamente ofensivo si se hace de manera incorrecta.
Nelson
49

¿Cuál de nosotros tiene razón?

Érase una vez, tu jefe era. Pero a medida que pasa el tiempo, las cosas cambian. Hoy en día lo eres (pero antes de correr hacia tu jefe, asegúrate de leer también la respuesta de Nelson ).

Las versiones antiguas de MySQL, y las versiones antiguas de casi todo , se manejaban mucho mejor con el Latin1 / ISO-8859-1 (5) más antiguo que UTF8.

Hay una razón por la cual UTF8 ha sido creado, evolucionado y empujado principalmente a todas partes: si se implementa correctamente, funciona mucho mejor . Hay algunos problemas de rendimiento y almacenamiento derivados del hecho de que un carácter Latin1 tiene 8 bits, mientras que un carácter UTF8 puede tener una longitud de 8 a 32 bits. Entonces, cuando planifique VARCHAR, debe tener esto en cuenta. Y sus rutinas de búsqueda serán un poco más lentas. Ellos serán capaces de hacer más cosas (por ejemplo, búsquedas con la sensibilidad de acento o sin . No se puede hacer sin los de Latin1 extenso trabajo), sino que se tome un poco más de tiempo.

Pero, por otro lado, el almacenamiento es barato , la sobrecarga realista en los tamaños de archivo es inferior al 2-3%, la potencia informática también es barata y se está volviendo más barata de acuerdo con la Ley de Moore; mientras que su tiempo y las expectativas de sus clientes definitivamente no lo son .

Es posible que tenga que preocuparse por las herramientas de búsqueda, etc. si fue usted quien desarrolló tales herramientas. Pero probablemente no lo seas. Usted utiliza estas herramientas; incluso los que ayer no eran completamente compatibles con UTF8 (como no lo eran los MySQL anteriores), lo son hoy o pronto lo serán (por ejemplo, MySQL con soporte utf8mb4).

Por lo tanto, al planificar e implementar cuidadosamente UTF8 de la manera correcta ( sin incluirlo en Latin1 como una ocurrencia tardía), puede obtener un código que sea razonablemente a prueba de futuro , lo que, si planea hacer negocios con cualquier país asiático, es muy bueno Cosa. Y si no tiene tales planes, otras personas lo tendrán, y esas personas podrían ser sus clientes, proveedores o socios.

Entonces, cuando comiencen a enviarle datos UTF8, tendrá que configurar una cosa complicada para convertir a Latin1 y lidiar con casos irresolubles.

Cuando tenga en cuenta en el presupuesto el costo de varias escaramuzas contra los malvados ninjas mojibake , y considere que no van a desaparecer , como ya descubrió, se dará cuenta de que ir a UTF8 no solo es más simple, sino que será más barato también.

LSerni
fuente
4

Algunas situaciones en las que restringir el conjunto de caracteres solo a ASCII puede tener sentido es para campos de elección limitada, por ejemplo, campos de estado, porque controla estrictamente los valores que pueden estar allí, y claves / referencias externas al sistema externo, porque rara vez hay razones para que tengan cualquier cosa menos caracteres alfanuméricos y algunos símbolos.

Para cualquier otro texto, solo use UTF-8.

Lie Ryan
fuente
2
¿MySQL no tiene enumeraciones?
raptortech97
2
Y dado que ASCII es un subconjunto de UTF8, solo use UTF8 incluso entonces.
RemcoGerlich
@RemcoGerlich: No estoy de acuerdo con que puedas usar UTF8 para esos. En mi opinión, las referencias externas no son texto, sino una secuencia opaca de bytes. No tienen juego de caracteres excepto por conveniencia de notación. Si la secuencia de bytes tiene una interpretación en cierto conjunto de caracteres, ese es el dominio del sistema externo o de la aplicación, no el de la base de datos.
Miente Ryan
3
@LieRyan: veo ese punto, pero tampoco debería ser ASCII, probablemente algún formato de blob binario más o menos.
RemcoGerlich
3

Para comenzar con la respuesta, no importa cómo esté configurado su servidor . La codificación de caracteres en MySQL podría configurarse por columna (es decir, la misma tabla podría contener caracteres en codificaciones múltiples, fácil). Es decir, mi servidor (y una serie de bases de datos heredadas) está configurado para cp1251 de forma predeterminada para clientes antiguos que no pueden establecer la clasificación correcta al conectarse (diferentes clientes de hardware), pero las bases de datos principales en producción están utilizando UTF-8.

Hablando de "espacio desperdiciado", no se puede considerar un desperdicio de datos importantes, ¿verdad? Sin embargo, el aumento del espacio de almacenamiento será diferente según el idioma en el que se encuentren sus datos. Desde un aumento insignificante (menos del 1%) si su sitio está principalmente en inglés y hasta un 100%, si es mailny utilizando caracteres fuera del rango ASCII . Y aún más, si te mueves más hacia el este. Las especificaciones posteriores de UTF-8 (denominadas UTF8mb4) permiten hasta 4 bytes por punto de código.

Y para "quién tiene razón" ... La verdad es que esta es una cuestión social más que técnica. Puede haber razones válidas para configuraciones de servidor específicas, pero debe conocer las implicaciones. Pero si me preguntas, no hay razón para no usar UTF-8. Es el único tipo que rige todos los textos del mundo.

AnrDaemon
fuente
MySQL intentará convertir datos en codificación de base de datos antes de convertirlos a codificación de columna. Si tiene un cliente utf8, una base de datos latin1 y una columna utf8, los datos de texto pueden perderse.
Ivan Solntsev
Ivan, esa es una pregunta completamente diferente. La interacción entre el conjunto de caracteres del cliente, el conjunto de caracteres del servidor, la conexión del conjunto de caracteres y los resultados del conjunto de caracteres es un artículo largo en la documentación de MySQL. Y en el caso de la configuración de clasificación por columna, la "clasificación de la base de datos" es la clasificación en columna, y se convierte directamente en el resultado del conjunto de caracteres, ignorando la clasificación en la base de datos.
AnrDaemon
0

Solo explíquele que UTF-8 es el valor predeterminado para el tráfico web. Y cualquier usuario puede ingresar cualquier carácter válido Unicode en su navegador.

Es mucho más fácil tener utf-8 / unicode desde el principio hasta el final que lidiar con los muchos y diversos problemas que resultan de utf-8-> latin-1-> utf-8.

James Anderson
fuente