Pregunta Cuál es la diferencia entre utf8_general_ci y utf8_unicode_ci


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


826
2018-04-20 03:43


origen


Respuestas:


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.


1267
2018-04-20 05:19



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%.


127
2018-03-02 02:53



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".


33
2018-01-01 00:31



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.


4
2018-04-20 04:09



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.


3
2018-03-06 11:51