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.