Indagamos por diferentes foros y así darte la solución para tu inquietud, si tienes alguna inquietud puedes dejarnos la duda y respondemos con gusto, porque estamos para ayudarte.
Solución:
Para aquellas personas que todavía llegan a esta pregunta en 2020 o más tarde, hay opciones más nuevas que pueden ser mejores que ambos de estos. Por ejemplo, utf8mb4_0900_ai_ci
.
Todas estas intercalaciones son para la codificación de caracteres UTF-8. Las diferencias están en cómo se ordena y compara el texto.
_unicode_ci
y _general_ci
Hay dos conjuntos de reglas diferentes para clasificar y comparar texto de la forma que esperamos. Las versiones más recientes de MySQL también introducen nuevos conjuntos de reglas, como _0900_ai_ci
para reglas equivalentes basadas en Unicode 9.0 – y sin equivalente _general_ci
variante. Las personas que lean esto ahora probablemente deberían usar una de estas intercalaciones más nuevas en lugar de _unicode_ci
o _general_ci
. La descripción de esas colaciones más antiguas a continuación se proporciona solo con fines de interés.
MySQL se encuentra actualmente en transición de una implementación UTF-8 defectuosa y antigua. Por ahora, necesitas usar utf8mb4
en lugar de utf8
para la parte de codificación de caracteres, para asegurarse de que está obteniendo la versión fija. La versión defectuosa permanece por compatibilidad con versiones anteriores, aunque está en desuso.
Diferencias clave
-
utf8mb4_unicode_ci
se basa en las reglas oficiales de Unicode para la clasificación y comparación universales, que clasifica con precisión en una amplia gama de idiomas. -
utf8mb4_general_ci
es un conjunto simplificado de reglas de clasificación que tiene como objetivo hacerlo lo mejor que puede mientras toma muchos atajos diseñados para mejorar la velocidad. No sigue las reglas Unicode y dará como resultado una clasificación o comparación no deseadas en algunas situaciones, como cuando se usan idiomas o caracteres particulares.En los servidores modernos, este aumento de rendimiento será casi insignificante. Fue ideado en una época en la que los servidores tenían una pequeña fracción del rendimiento de la CPU de las computadoras actuales.
Beneficios de utf8mb4_unicode_ci
sobre utf8mb4_general_ci
utf8mb4_unicode_ci
, que usa las reglas Unicode para ordenar y comparar, emplea un algoritmo bastante complejo para ordenar correctamente en una amplia gama de idiomas y cuando usa una amplia gama de caracteres especiales. Estas reglas deben tener en cuenta las convenciones específicas del idioma; no todo el mundo clasifica a sus personajes en lo que llamaríamos “orden alfabético”.
En lo que respecta a los idiomas latinos (es decir, “europeos”), no hay mucha diferencia entre el ordenamiento Unicode y el simplificado utf8mb4_general_ci
ordenar en MySQL, pero todavía hay algunas diferencias:
-
Por ejemplo, la intercalación Unicode clasifica “ß” como “ss” y “Œ” como “OE” como las personas que usan esos caracteres normalmente querrían, mientras que
utf8mb4_general_ci
los clasifica como caracteres individuales (presumiblemente como “s” y “e” respectivamente). -
Algunos caracteres Unicode se definen como ignorables, lo que significa que no deben contar para el orden de clasificación y la comparación debe pasar al siguiente carácter.
utf8mb4_unicode_ci
maneja estos correctamente.
En idiomas no latinos, como idiomas asiáticos o idiomas con alfabetos diferentes, puede haber muchos más diferencias entre la ordenación Unicode y la simplificada utf8mb4_general_ci
clasificación. La idoneidad de utf8mb4_general_ci
Dependerá en gran medida del idioma 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 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. Es casi seguro que su base de datos estará limitada por otros cuellos de botella además de este.
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 en día, ese costo de rendimiento prácticamente ha desaparecido y los desarrolladores están tratando la internacionalización con más seriedad.
Se puede argumentar que si la velocidad es más importante para usted que la precisión, es mejor que no haga ninguna clasificación. Es trivial hacer un algoritmo más rápido si no necesita que sea preciso. Entonces, utf8mb4_general_ci
es un compromiso que probablemente no sea necesario por razones de velocidad y probablemente tampoco sea adecuado por razones de precisión.
Otra cosa que agregaré es que incluso si sabe que su aplicación solo es compatible con el idioma inglés, es posible que deba lidiar con los nombres de las personas, que a menudo pueden contener caracteres utilizados en otros idiomas en los que es igualmente importante ordenarlos correctamente. . El uso de las reglas Unicode para todo ayuda a tener la tranquilidad de que la gente inteligente de Unicode ha trabajado muy duro para que la clasificación funcione correctamente.
Que significan las partes
Primeramente, ci
es para no distingue entre mayúsculas y minúsculas clasificación y comparación. Esto significa que es adecuado para datos textuales y el uso de mayúsculas y minúsculas no es importante. Los otros tipos de colación son cs
(distingue entre mayúsculas y minúsculas) para datos textuales donde las mayúsculas y minúsculas son importantes, y bin
, para donde la codificación debe coincidir, bit por bit, lo cual es adecuado para campos que son realmente datos binarios codificados (incluyendo, por ejemplo, Base64). La clasificación que distingue entre mayúsculas y minúsculas conduce a algunos resultados extraños y la comparación entre mayúsculas y minúsculas puede dar como resultado valores duplicados que difieren solo en mayúsculas y minúsculas, por lo que las intercalaciones que distinguen entre mayúsculas y minúsculas están cayendo en desgracia para los datos textuales; si el caso es importante para usted, entonces, la puntuación es ignorable. y así sucesivamente probablemente también sea significativo, y una intercalación binaria podría ser más apropiada.
Próximo, unicode
o general
se refiere a las reglas específicas de clasificación y comparación, en particular, la forma en que se normaliza o compara el texto. Hay muchos conjuntos de reglas diferentes para la codificación de caracteres utf8mb4, con unicode
y general
siendo dos que intentan funcionar bien en todos los idiomas posibles en lugar de uno específico. Las diferencias entre estos dos conjuntos de reglas son el tema de esta respuesta. Tenga en cuenta que unicode
utiliza reglas de Unicode 4.0. Las versiones recientes de MySQL agregan los conjuntos de reglas unicode_520
usando reglas de Unicode 5.2, y 0900
(eliminando la parte “unicode_”) usando reglas de Unicode 9.0.
Y por último, utf8mb4
es, por supuesto, la codificación de caracteres utilizada internamente. En esta respuesta, estoy hablando solo de codificaciones basadas en Unicode.
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í crearlo yo mismo.
Creé 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;
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 simples SELECT
, SELECT
con LIKE
y ordenando (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 anteriores utf8_general_ci
se utiliza la intercalación, pero, por supuesto, durante las pruebas utilicé tanto utf8_general_ci
y 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
: 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
en un 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
en un 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
en un 7,9%.
Esta publicación lo describe muy bien.
En breve: utf8_unicode_ci
utiliza el algoritmo de clasificació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”.
Recuerda que puedes dar recomendación a este artículo si si solucionó tu problema.