Pergunta

Entre utf8_general_ci e utf8_unicode_ci, existem diferenças em termos de desempenho?

Foi útil?

Solução

Estes dois agrupamentos são tanto para a codificação de caracteres UTF-8. As diferenças estão em como o texto é classificado e comparados.

Nota: Desde o MySQL 5.5.3 você deve usar utf8mb4 em vez de utf8. Ambos referem-se a codificação UTF-8, mas o utf8 mais velho tinha uma limitação específica do MySQL prevenção do uso de caracteres numeradas acima 0xFFFD.

Principais diferenças

  • utf8mb4_unicode_ci é baseado nas regras oficiais Unicode para a classificação e comparação universal, que classifica com precisão em uma ampla variedade de idiomas.

  • utf8mb4_general_ci é um conjunto simplificado de regras de classificação que pretende fazer, assim como ele pode ao mesmo tempo levando muitos atalhos projetados para melhorar a velocidade. Não seguir as regras Unicode e irá resultar em separação indesejável ou comparação em algumas situações, como quando se usa idiomas ou caracteres específicos.

    Em servidores modernos, este aumento de desempenho será tudo menos insignificante. Ele foi criado em uma época em que os servidores tinha uma pequena fração do desempenho da CPU dos computadores de hoje.

Nota: existe agora uma versão atualizada do utf8mb4_unicode_ci chamado utf8mb4_0900_ai_ci - isto é baseado em mudanças no Unicode versão 9.0, e também é aparentemente mais rápido. Adota um novo esquema de nomes pelo qual 0900 é o Unicode versão e ai meios acento-insensitive -. Como o utf8mb4_unicode_ci anterior, acentos em letras não são considerados significativos

Benefícios da utf8mb4_unicode_ci mais utf8mb4_general_ci

utf8mb4_unicode_ci, que usa as regras Unicode para classificação e comparação, emprega um algoritmo bastante complexo para classificação correta em uma ampla variedade de línguas e ao usar uma ampla gama de caracteres especiais. Estas regras devem ter em conta convenções específicas para a linguagem; nem toda a gente classifica seus personagens no que poderíamos chamar de 'ordem alfabética'.

Quanto latino (ie "europeu") línguas ir, não há muita diferença entre o Unicode classificação e o utf8mb4_general_ci simplificado ordenação em MySQL, mas ainda existem algumas diferenças:

  • Por exemplo, os tipos de agrupamento Unicode "ss" como "ss", e "OE" como "OE" como pessoas que usam esses personagens normalmente querem, enquanto os tipos utf8mb4_general_ci como caracteres simples (presumivelmente como "s "e "e", respectivamente).

  • Alguns caracteres Unicode são definidos como ignorável, o que significa que eles não devem contar para a ordem de classificação ea comparação deve passar para o próximo caractere em seu lugar. alças utf8mb4_unicode_ci estes corretamente.

Em idiomas não-latinos, como idiomas asiáticos ou idiomas com alfabetos diferentes, pode haver um monte mais diferenças entre Unicode triagem e o utf8mb4_general_ci simplificado de classificação. A adequação de utf8mb4_general_ci vai depender muito da linguagem utilizada. Para alguns idiomas, ele vai ser bastante inadequada.

O que você deve usar?

Há quase certamente nenhuma razão para usar utf8mb4_general_ci mais, como já deixou para trás o ponto onde a velocidade da CPU é baixo o suficiente para que a diferença de desempenho seria importante. Seu banco de dados irá quase certamente ser limitado por outros gargalos que isso.

No passado, algumas pessoas recomendado para uso utf8mb4_general_ci exceto quando a classificação exata ia ser bastante importante para justificar o custo desempenho. Hoje, esse custo desempenho praticamente desapareceu, e os desenvolvedores estão tratando internacionalização mais a sério.

Há um argumento a ser feito que, se a velocidade é mais importante para você do que a precisão, você pode muito bem não fazer qualquer triagem em tudo. É trivial para fazer umalgoritmo mais rápido se você não precisa dele para ser exato. Então, utf8mb4_general_ci é um compromisso que provavelmente não é necessário por razões de velocidade e provavelmente também não é adequado, por razões de precisão.

Uma outra coisa que vou acrescentar é que mesmo se você sabe que seu aplicativo suporta apenas o idioma Inglês, ele ainda pode precisar para lidar com os nomes das pessoas, que muitas vezes podem conter caracteres utilizados em outras línguas em que é tão importante para classificar corretamente. Usando as regras Unicode para tudo ajuda a adicionar a paz de espírito que as pessoas Unicode muito inteligentes têm trabalhado muito duro para fazer a triagem trabalho corretamente.

O que as partes significa

Em primeiro lugar, ci é para case-insensitive classificação e comparação. Isto significa que é adequado para dados textuais, e caso não é importante. Os outros tipos de agrupamento são cs (caso-sensível) para dados textuais em que caso é importante, e bin, para onde as necessidades de codificação para corresponder, bit a bit, o que é adequado para campos que são realmente codificados dados binários (incluindo, por exemplo, na base 64). sensível ao caso leva de classificação para alguns resultados estranhos e comparação entre maiúsculas e minúsculas pode resultar em valores duplicados, diferindo apenas em caso de letra, de modo agrupamentos maiúsculas de minúsculas estão caindo em desuso para dados textuais - se caso é significativo para você, de pontuação, em seguida, caso contrário ignorable e assim por diante é, provavelmente, também significativa, e um agrupamento binário pode ser mais apropriado.

Em seguida, unicode ou general refere-se à específica classificação e regras de comparação - em particular, a maneira como o texto é normalizado ou comparação. Há muitos diferentes conjuntos de regras para a codificação de caracteres utf8mb4, com unicode e general sendo dois que tentar trabalhar bem em todas as línguas possíveis, em vez de um um específico. As diferenças entre estes dois conjuntos de regras são objecto desta resposta. Note-se que os conjuntos de regras mais recentes incluem 0900 referindo-se a Unicode 9.0 e unicode_520 referindo-se a Unicode 5.2.

E, por último, utf8mb4 é, naturalmente, a codificação de caracteres usado internamente. Nesta resposta que eu estou falando apenas sobre codificações base Unicode.

Outras dicas

Eu queria saber qual é a diferença de desempenho entre usando utf8_general_ci e utf8_unicode_ci, mas eu não encontrei qualquer referência listados na internet, então eu decidi criar benchmarks mim mesmo.

Eu criei uma tabela muito simples, com 500.000 linhas:

CREATE TABLE test(
  ID INT(11) DEFAULT NULL,
  Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;

Então eu encheu-o com dados aleatórios executando este procedimento armazenado:

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

Então eu criei os seguintes procedimentos armazenados para referência simples SELECT, SELECT com LIKE, e classificação (SELECT com 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;

Nos procedimentos acima armazenados agrupamento utf8_general_ci é utilizado, mas é claro que durante os testes que utilizado tanto utf8_general_ci e utf8_unicode_ci.

I chamado cada procedimento armazenado 5 vezes para cada agrupamento (5 vezes para utf8_general_ci e 5 vezes para utf8_unicode_ci) e, em seguida, calculados os valores médios.

Meus resultados são:

benchmark_simple_select()

  • com utf8_general_ci: 9,957 ms
  • com utf8_unicode_ci: 10.271 ms

Neste referência usando utf8_unicode_ci é mais lento do que utf8_general_ci de 3,2%.

benchmark_select_like()

  • com utf8_general_ci: 11,441 ms
  • com utf8_unicode_ci: 12,811 ms

Neste referência usando utf8_unicode_ci é mais lento do que utf8_general_ci em 12%.

benchmark_order_by()

  • com utf8_general_ci: 11.944 ms
  • com utf8_unicode_ci: 12.887 ms

Nesta referência usando utf8_unicode_ci é mais lento do que utf8_general_ci de 7,9%.

Este post descreve-o muito bem.

Em suma: utf8_unicode_ci utiliza a Collation Algorithm Unicode conforme definido nas normas Unicode, enquanto utf8_general_ci é uma forma mais simples ordem de classificação que resulta em resultados "menos precisos" Classificando

.

Consulte o manual do mysql, Unicode conjuntos de caracteres seção:

Para qualquer conjunto de caracteres Unicode, operações realizadas utilizando o agrupamento _general_ci são mais rápidos do que aqueles para o agrupamento _unicode_ci. Por exemplo, as comparações para o utf8_general_ci agrupamento são mais rápidos, mas um pouco menos correta, do que comparações para utf8_unicode_ci. o razão para isso é que suporta utf8_unicode_ci mapeamentos, tais como expansões; isto é, quando um caráter compara igual a combinações de outros caracteres. Para exemplo, em alemão e em algum outro línguas “ß” é igual a “ss”. utf8_unicode_ci também suporta contrações e personagens ignorable. utf8_general_ci é um agrupamento legado que não suporta expansões, contrações, ou caracteres ignorable. Pode fazer apenas um-para-um comparações entre personagens.

Assim, para resumir, utf_general_ci usa um conjunto menor e menos correta (de acordo com o padrão) de comparações que utf_unicode_ci que deve implementar todo o padrão. O conjunto general_ci será mais rápido porque há menos computação para fazer.

Em breves palavras:

Se você precisar melhorar a ordenação ordem - uso utf8_unicode_ci (este é o método preferido),

mas se interessou totalmente no desempenho -. Uso utf8_general_ci, mas sei que é um pouco desatualizado

As diferenças em termos de desempenho são muito ligeira.

Alguns detalhes (PL)

Como podemos ler aqui ( Peter Gulutzan ) há diferença na triagem / comparando carta polonês "L" (L com acidente vascular cerebral - html esc: Ł) ( minúsculas: "L" - html esc: ł) - temos seguinte suposição:

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

Em polonês carta linguagem Ł é depois de carta L e antes M. Ninguém desta codificação é melhor ou pior - que depende de suas necessidades.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top