¿Cuál es la diferencia entre utf8_general_ci y utf8_unicode_ci
-
12-09-2019 - |
Pregunta
Entre utf8_general_ci
y utf8_unicode_ci
, ¿existen diferencias en términos de rendimiento?
Solución
Estos dos colaciones son tanto para el UTF-8 codificación de caracteres. Las diferencias están en cómo se clasifica y se compara el texto.
Nota: Desde MySQL 5.5.3 se debe utilizar utf8mb4
en lugar de utf8
. Ambos se refieren a la codificación UTF-8, pero el utf8
más tenían una limitación específica de MySQL prevenir el uso de caracteres numerados de arriba 0xFFFD.
Las diferencias clave
-
utf8mb4_unicode_ci
se basa en las normas oficiales Unicode para la clasificación y comparación universal, que ordena con precisión en una amplia gama de idiomas. -
utf8mb4_general_ci
es un conjunto simplificado de reglas de ordenación que tiene como objetivo hacer lo mejor que pueda, teniendo muchos atajos diseñados para mejorar la velocidad. No se sigue las reglas Unicode y dará lugar a la clasificación indeseable o comparación en algunas situaciones, como cuando se utilizan lenguajes o caracteres particulares.En los servidores modernos, este aumento de rendimiento es todo, pero insignificante. Fue ideado en un momento en que los servidores tenían una pequeña fracción del rendimiento de la CPU de los ordenadores de hoy en día.
Nota: existe ahora una versión actualizada de utf8mb4_unicode_ci
llamada utf8mb4_0900_ai_ci
- esto se basa en los cambios en la versión 9.0 de Unicode, y también es aparentemente más rápido. Se adopta un nuevo esquema de nombres mediante el cual 0900
es la versión Unicode y ai
significa acento insensible -. utf8mb4_unicode_ci
como el anterior, los acentos en las letras no son considerados significativos
Beneficios de utf8mb4_unicode_ci
más utf8mb4_general_ci
utf8mb4_unicode_ci
, que utiliza las reglas 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 normas deben tener en cuenta las convenciones específicas del lenguaje; no todo el mundo ordena a sus personajes en lo que llamaríamos 'orden alfabético'.
En cuanto a latinos (es decir, "europeo") van idiomas, no hay mucha diferencia entre la clasificación de Unicode y la utf8mb4_general_ci
simplificado de clasificación en MySQL, pero todavía hay algunas diferencias:
-
Para ejemplos, el tipo de intercalación Unicode "SS" como "ss", y "OE" como "OE" como personas que utilizan esos caracteres que normalmente quieren, mientras que
utf8mb4_general_ci
los clasifica como caracteres individuales (presumiblemente como "s "y "e", respectivamente). -
Algunos caracteres Unicode se definen como ignorable, lo que significa que no deben contar para el orden y la comparación deberá pasar al siguiente carácter en su lugar.
utf8mb4_unicode_ci
maneja éstos correctamente.
En idiomas no latinos, tales como idiomas asiáticos o idiomas con alfabetos diferentes, puede haber una gran cantidad de más diferencias entre la clasificación y la clasificación Unicode utf8mb4_general_ci
simplificado. La idoneidad de utf8mb4_general_ci
dependerá en gran medida del lenguaje utilizado. Para algunos idiomas, que va a ser bastante inadecuado.
¿Qué se debe utilizar?
No hay casi ciertamente ninguna razón para utilizar utf8mb4_general_ci
más, como ya hemos dejado atrás el punto en el que la velocidad de la CPU es suficientemente baja para que la diferencia de rendimiento sería importante. Su base de datos es casi seguro que estar limitado por otros cuellos de botella que esto.
En el pasado, algunas personas recomiendan utilizar utf8mb4_general_ci
excepto cuando clasificación precisa iba a ser lo suficientemente importante como para justificar el costo de rendimiento. Hoy, ese costo de rendimiento prácticamente ha desaparecido, y los desarrolladores están tratando de internacionalización más en serio.
Hay un argumento para afirmar que si la velocidad es más importante para usted que la precisión, es posible que así no lo hace ninguna clasificación en absoluto. Es trivial para hacer unaalgoritmo más rápido si no lo necesita para ser exactos. Así, utf8mb4_general_ci
es un compromiso que probablemente no se necesita por razones de velocidad y probablemente también no es adecuado por razones de precisión.
Otra cosa voy a añadir es que incluso si usted sabe que su aplicación sólo es compatible con el idioma Inglés, todavía puede tener que lidiar con los nombres de las personas, que a menudo puede contener caracteres utilizados en otros idiomas en los que es tan importante para ordenar correctamente. Utilizando las reglas Unicode para todo, ayuda a añadir la tranquilidad de que la gente Unicode muy inteligentes han trabajado muy duro para hacer la ordenación trabajo correctamente.
¿Qué significan las partes
En primer lugar, ci
es para entre mayúsculas y minúsculas clasificación y comparación. Esto significa que es adecuado para datos de texto, y el caso no es importante. Los otros tipos de intercalación son cs
(mayúsculas y minúsculas) para datos de texto donde caso es importante, y bin
, por donde la codificación debe coincidir, bit por bit, que es adecuado para los campos que están realmente codificados datos binarios (incluyendo, por ejemplo, Base64). clasificación entre mayúsculas y minúsculas conduce a resultados un tanto extraños y la comparación entre mayúsculas y minúsculas puede dar lugar a valores duplicados que difieren sólo en mayúsculas y minúsculas, por lo que las intercalaciones mayúsculas y minúsculas están cayendo en desuso para datos de texto - si el caso es importante para usted, puntuacion pues de lo contrario puede ignorarse y así sucesivamente es probable que también significativa, y una colación binaria puede ser más apropiado.
A continuación, unicode
o general
refiere a las reglas de clasificación y comparación específica - en particular, el texto forma es normalizado o comparación. Hay muchos juegos diferentes de reglas para el carácter utf8mb4 codificación, con unicode
y general
siendo dos que tratan de trabajar bien en todos los idiomas posibles en lugar de a uno en especial. Las diferencias entre estos dos conjuntos de normas son objeto de esta respuesta. Tenga en cuenta que los nuevos conjuntos de reglas incluyen 0900
refiriéndose a Unicode 9.0 y unicode_520
refiriéndose a Unicode 5.2.
Y por último, utf8mb4
es, por supuesto, la codificación de caracteres utilizado internamente. En esta respuesta Estoy hablando sólo de codificaciones basado en Unicode.
Otros consejos
Yo quería saber lo que es la diferencia de rendimiento entre el uso de utf8_general_ci
y utf8_unicode_ci
, pero no he encontrado ninguna referencia que figuran en el Internet, por lo que decidí crear puntos de referencia a mí mismo.
He creado una tabla muy simple, con 500.000 filas:
CREATE TABLE test(
ID INT(11) DEFAULT NULL,
Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
Entonces me empapó de datos aleatorios mediante la ejecución de 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 he creado los siguientes procedimientos almacenados a SELECT
referencia simple, SELECT
con LIKE
, y clasificación (SELECT
con ORDER BY
):
CREATE PROCEDURE 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 por encima de intercalación utf8_general_ci
se utiliza, pero por supuesto durante las pruebas que utilizan tanto utf8_general_ci
y utf8_unicode_ci
.
I 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 calcula entonces los valores medios.
Mis resultados son los siguientes:
benchmark_simple_select()
- con
utf8_general_ci
: 9.957 ms - con
utf8_unicode_ci
: 10,271 ms
En este punto de referencia usando utf8_unicode_ci
es más lento que utf8_general_ci
por 3,2%.
benchmark_select_like()
- con
utf8_general_ci
: 11.441 ms - con
utf8_unicode_ci
: 12.811 ms
En este punto de referencia usando utf8_unicode_ci
es más lento que utf8_general_ci
por 12%.
benchmark_order_by()
- con
utf8_general_ci
: 11.944 ms - con
utf8_unicode_ci
: 12.887 ms
En este punto de referencia usando utf8_unicode_ci
es más lento que utf8_general_ci
por 7,9%.
Este post lo describe muy bien.
En resumen:. Utf8_unicode_ci utiliza el Unicode Algoritmo de clasificación tal como se define en las normas Unicode, mientras que utf8_general_ci es un orden de clasificación más simple que da lugar a resultados menos precisos "" Clasificación
Consulte el manual de MySQL, conjuntos de caracteres Unicode sección:
Para cualquier conjunto de caracteres Unicode, operaciones realizaron utilizando el cotejo _general_ci son más rápidos que los de la colación _unicode_ci. Por ejemplo, las comparaciones para el utf8_general_ci cotejo son más rápidos, pero un poco menos correcta, de lo comparaciones para utf8_unicode_ci. los razón de esto es que utf8_unicode_ci admite asignaciones tales como expansiones; es decir, cuando uno personaje resulta igual a una combinaciones de otros personajes. por ejemplo, en alemán y en alguna otra lenguas “ß” es igual a “ss”. utf8_unicode_ci también soporta contracciones y personajes que pueden ignorarse. utf8_general_ci es una colación legado que no admite ampliaciones, contracciones, o caracteres que pueden ignorarse. Sólo uno-a-uno puede hacer comparaciones entre los personajes.
Para resumir, utf_general_ci utiliza un conjunto más pequeño y menos correcta (según el estándar) de las comparaciones que utf_unicode_ci la que debería en práctica totalidad de la norma. El conjunto general_ci será más rápido porque hay menos cómputo de hacer.
En breves palabras:
Si necesita un mejor orden de clasificación - uso utf8_unicode_ci
(este es el método preferido),
pero si totalmente interesado en el rendimiento -. utf8_general_ci
uso, pero sabemos que es un poco anticuado
Las diferencias en términos de rendimiento son muy leves.
Algunos detalles (PL)
Como podemos leer aquí ( Peter Gulutzan ) hay una diferencia en la clasificación / comparación carta pulir "L" (L con un accidente cerebrovascular - html esc: Ł
) ( minúsculas: "L" - html esc: ł
) - hemos supuesto siguiente:
utf8_polish_ci Ł greater than L and less than M
utf8_unicode_ci Ł greater than L and less than M
utf8_unicode_520_ci Ł equal to L
utf8_general_ci Ł greater than Z
En el pulimento carta lenguaje Ł
es después de la carta L
y antes M
. Nadie de esta codificación es mejor o peor - que depende de sus necesidades.