Entre utf8_general_ci
y utf8_unicode_ci
, ¿hay alguna diferencia en términos de rendimiento?
Entre utf8_general_ci
y utf8_unicode_ci
, ¿hay alguna diferencia en términos de rendimiento?
Estas dos intercalaciones 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
más bien que utf8
. Ambos se refieren a la codificación UTF-8, pero el antiguo 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 ordena con precisión en una amplia gama de idiomas.
utf8mb4_general_ci
no implementa todas las reglas de ordenamiento Unicode, lo que dará lugar a una clasificación no deseada en algunas situaciones, como cuando se utilizan determinados idiomas o caracteres.
Actuación
utf8mb4_general_ci
es más rápido en las comparaciones y la clasificación, ya que requiere un conjunto de atajos relacionados con el rendimiento.
En servidores modernos, este aumento de rendimiento será casi insignificante. Fue ideado en una época en que los servidores tenían una pequeña fracción del rendimiento de la CPU de las computadoras de hoy en día.
utf8mb4_unicode_ci
, que utiliza las reglas Unicode para ordenar y comparar, emplea un algoritmo bastante complejo para una clasificación correcta en una amplia gama de idiomas y al utilizar una amplia gama de caracteres especiales. Estas reglas deben tener en cuenta las convenciones específicas del idioma; no todos clasifican a 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 simplificada. utf8mb4_general_ci
ordenando en MySQL, pero todavía hay algunas diferencias:
Por ejemplo, la intercalación Unicode clasifica "ß" como "ss", y "Œ" como "OE", como las personas que utilizan esos caracteres normalmente querrían, mientras que utf8mb4_general_ci
los clasifica como caracteres únicos (presumiblemente como "s" y "e", respectivamente).
Algunos caracteres Unicode se definen como ignorables, lo que significa que no deben tenerse en cuenta para el orden de clasificación y la comparación debe pasar al siguiente carácter. utf8mb4_unicode_ci
maneja esto apropiadamente
En idiomas no latinos, como idiomas asiáticos o idiomas con diferentes alfabetos, puede haber muchos Más diferencias entre la clasificación Unicode y el simplificado utf8mb4_general_ci
clasificación. La idoneidad de utf8mb4_general_ci
dependerá en gran medida del lenguaje utilizado. Para algunos idiomas, será bastante inadecuado.
¿Qué deberías usar?
Es casi seguro que no hay razón para usar utf8mb4_general_ci
ya que dejamos atrás el punto donde la velocidad de la CPU es lo suficientemente baja para que la diferencia de rendimiento sea importante. Su base de datos casi seguramente estará limitada por otros cuellos de botella que esto.
La diferencia en el rendimiento solo se podrá medir 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 debe ser alta en la lista de cosas para solucionar problemas.
En el pasado, algunas personas recomendaban usar utf8mb4_general_ci
excepto cuando una clasificación precisa iba a ser lo suficientemente importante como para justificar el costo de rendimiento. Hoy, ese costo de rendimiento casi ha desaparecido, y los desarrolladores están tratando la internacionalización más en serio.
Otra cosa que agregaré es que incluso si sabes que tu aplicación solo admite el idioma inglés, es posible que deba tratar con los nombres de las personas, que a menudo pueden contener caracteres utilizados en otros idiomas en los que es tan importante clasificar correctamente . El uso de las reglas de Unicode para todo ayuda a agregar 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 el uso de utf8_general_ci y utf8_unicode_ci, pero no encontré ninguna referencia listada en Internet, así que decidí crear puntos de referencia yo mismo.
Creé 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 los parámetros SELECT, SELECT con LIKE y Sorting (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 intercalación utf8_general_ci, pero por supuesto durante las pruebas utilicé utf8_general_ci y utf8_unicode_ci.
Llamé a cada procedimiento almacenado 5 veces para cada colació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, el uso de 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 el uso de 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 el uso de utf8_unicode_ci es más lento que utf8_general_ci en 7.9%.
Esta publicación lo describe muy bien.
En resumen: utf8_unicode_ci usa el Algoritmo de intercalación Unicode como se define en los estándares 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".
Ver el manual de mysql, Juegos de caracteres Unicode sección:
Para cualquier conjunto de caracteres Unicode, operaciones realizadas usando el _general_ci intercalación es más rápido que los de la intercalación _unicode_ci. Por ejemplo, comparaciones para el la intercalación utf8_general_ci es más rápida, pero un poco menos correcto, que comparaciones para utf8_unicode_ci. los razón por esto es que utf8_unicode_ci admite asignaciones tales como expansiones; es decir, cuando uno 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 es compatible contracciones y personajes ignorables. utf8_general_ci es una colación heredada eso no admite expansiones, contracciones, o personajes ignorables. Puede hacer solo uno a uno comparaciones entre personajes.
Para resumir, utf_general_ci usa un conjunto de comparaciones más pequeño y menos correcto (de acuerdo con el estándar) que utf_unicode_ci que debería implementar todo el estándar. El conjunto general_ci será más rápido porque hay menos cálculos que hacer.
En palabras breves:
Si necesita ordenar mejor, use utf8_unicode_ci
(Este es el método preferido),
pero si está completamente interesado en el rendimiento, use utf8_general_ci
, pero debes saber que está un poco desactualizado.
Las diferencias en términos de rendimiento son muy leves.