Pregunta

Entre utf8_general_ci y utf8_unicode_ci, ¿existen diferencias en términos de rendimiento?

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top