utf8mb4_unicode_ci utf8_unicode_ci utf8_spanish_ci utf8_general_ci spanish charset change mysql unicode

mysql - utf8_spanish_ci - ¿Cuál es la diferencia entre utf8_general_ci y utf8_unicode_ci



utf8_unicode_ci mysql (5)

Entre utf8_general_ci y utf8_unicode_ci , ¿hay alguna diferencia en términos de rendimiento?


Consulte el manual de mysql, sección Conjuntos de caracteres Unicode :

Para cualquier conjunto de caracteres Unicode, las operaciones realizadas utilizando la intercalación _general_ci son más rápidas que las de la intercalación _unicode_ci. Por ejemplo, las comparaciones para la compilación utf8_general_ci son más rápidas, pero ligeramente 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 carácter se compara como igual a combinaciones de otros caracteres. Por ejemplo, en alemán y en algunos otros idiomas, "ß" es igual a "ss". utf8_unicode_ci también admite contracciones y caracteres ignorables. utf8_general_ci es una compilación heredada que no admite expansiones, contracciones ni caracteres ignorables. Solo puede hacer comparaciones uno a uno entre los personajes.

Entonces, para resumir, utf_general_ci utiliza un conjunto de comparaciones más pequeño y menos correcto (según el estándar) que utf_unicode_ci que debe implementar todo el estándar. El conjunto general_ci será más rápido porque hay menos cálculos que hacer.


Estas dos colaciones son ambas para la codificación de caracteres UTF-8. Las diferencias están en cómo se clasifica y se compara el texto.

Nota: Desde MySQL 5.5.3 debes usar utf8mb4 lugar de utf8 . Ambos se refieren a la codificación UTF-8, pero el utf8 más utf8 tenía una limitación específica de MySQL que impedía el uso de caracteres numerados por encima de 0xFFFD.

  • Exactitud

    utf8mb4_unicode_ci se basa en el estándar Unicode para clasificación y comparación, que se clasifica con precisión en una amplia gama de idiomas.

    utf8mb4_general_ci no implementa todas las reglas de clasificación de Unicode, lo que resultará en una clasificación no deseada en algunas situaciones, como cuando se usan idiomas o caracteres específicos.

  • Actuación

    utf8mb4_general_ci es más rápido en las comparaciones y en la clasificación, ya que requiere un montón de accesos directos relacionados con el rendimiento.

    En los servidores modernos, este aumento de rendimiento será casi insignificante. Se diseñó en una época en que los servidores tenían una pequeña fracción del rendimiento de la CPU de las computadoras de hoy.

    utf8mb4_unicode_ci , que utiliza las reglas de Unicode para la clasificación y comparación, emplea un algoritmo bastante complejo para la clasificación correcta en una amplia gama de idiomas y cuando se utiliza una amplia gama de caracteres especiales. Estas reglas deben tener en cuenta las convenciones específicas del idioma; no todo el mundo clasifica sus personajes en lo que llamaríamos "orden alfabético".

En cuanto a los idiomas latinos (es decir, "europeos"), no hay mucha diferencia entre la clasificación Unicode y la clasificación simplificada utf8mb4_general_ci en MySQL, pero todavía hay algunas diferencias:

  • Por ejemplo, la recopilación de Unicode clasifica "ß" como "ss", y "" como "OE" como querrían las personas que usan esos caracteres, mientras que utf8mb4_general_ci clasifica como caracteres únicos (probablemente como "s" y "e" respectivamente ).

  • Algunos caracteres Unicode se definen como ignorables, lo que significa que no deben contar para el orden y la comparación debe pasar al siguiente carácter. utf8mb4_unicode_ci maneja estos adecuadamente.

En idiomas no latinos, como los idiomas asiáticos o idiomas con diferentes alfabetos, puede haber muchas más diferencias entre la clasificación Unicode y la clasificación simplificada utf8mb4_general_ci . La idoneidad de utf8mb4_general_ci dependerá en gran medida del idioma utilizado. Para algunos idiomas, será bastante inadecuado.

¿Qué debes usar?

Es casi seguro que ya no hay razón para usar utf8mb4_general_ci , ya que hemos dejado atrás el punto donde la velocidad de la CPU es lo suficientemente baja como para que la diferencia de rendimiento sea importante. Su base de datos casi seguramente estará limitada por otros cuellos de botella que no sean estos.

La diferencia en el rendimiento solo será medible en situaciones extremadamente especializadas, y si ese es usted, probablemente ya lo sepa. Si experimenta una clasificación lenta, en casi todos los casos será un problema con sus índices / plan de consulta. Cambiar la función de intercalación no debería ocupar un lugar destacado en la lista de cosas para solucionar.

En el pasado, algunas personas recomendaban usar utf8mb4_general_ci excepto cuando la clasificación precisa iba a ser lo suficientemente importante como para justificar el costo de rendimiento. Hoy en día, el costo de rendimiento prácticamente ha desaparecido, y los desarrolladores están tratando la internacionalización más seriamente.

Otra cosa que agregaré es que incluso si sabe que su aplicación solo es compatible con el idioma inglés, es posible que tenga que tratar con los nombres de las personas, que a menudo pueden contener caracteres utilizados en otros idiomas en los que es tan importante clasificarlos correctamente. . El uso de las reglas de Unicode para todo ayuda a tener la tranquilidad de que las personas muy inteligentes de Unicode han trabajado muy duro para que la clasificación funcione correctamente.


Quería saber cuál es la diferencia de rendimiento entre usar utf8_general_ci y utf8_unicode_ci, pero no encontré ningún punto de referencia en Internet, así que decidí crear puntos de referencia yo mismo.

He creado una tabla muy simple con 500000 filas:

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

Luego lo llené con datos aleatorios ejecutando este procedimiento almacenado:

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

Luego creé los siguientes procedimientos almacenados para comparar SELECT simple, SELECT con LIKE y clasificación (SELECT con ORDER BY):

CREATE 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

En los procedimientos almacenados anteriores se usa la compilación utf8_general_ci, pero, por supuesto, durante las pruebas usé tanto utf8_general_ci como utf8_unicode_ci.

Llamé a cada procedimiento almacenado 5 veces para cada intercalación (5 veces para utf8_general_ci y 5 veces para utf8_unicode_ci) y luego calculé los valores promedio.

Mis resultados son:

benchmark_simple_select () con utf8_general_ci: 9957 ms
benchmark_simple_select () con utf8_unicode_ci: 10271 ms
En este punto de referencia, usar utf8_unicode_ci es más lento que utf8_general_ci en un 3.2%.

benchmark_select_like () con utf8_general_ci: 11441 ms
benchmark_select_like () con utf8_unicode_ci: 12811 ms
En este punto de referencia, usar utf8_unicode_ci es más lento que utf8_general_ci en un 12%.

benchmark_order_by () con utf8_general_ci: 11944 ms
benchmark_order_by () con utf8_unicode_ci: 12887 ms
En este punto de referencia, usar utf8_unicode_ci es más lento que utf8_general_ci en un 7.9%.


Este post lo describe muy bien.

En resumen: utf8_unicode_ci utiliza el algoritmo de clasificación de Unicode tal como se define en los estándares de Unicode, mientras que utf8_general_ci es un orden de clasificación más simple que da como resultado resultados de clasificación "menos precisos".


En pocas palabras:

Si necesita un mejor orden de clasificación, use utf8_unicode_ci (este es el método preferido),

pero si está completamente interesado en el rendimiento, use utf8_general_ci , pero sepa que está un poco desactualizado.

Las diferencias en términos de rendimiento son muy leves.