Se você gosta utf8[mb4]_unicode_ci, você pode gostar utf8[mb4]_unicode_520_ciainda mais.
Rick James
8
Não sei como me sinto sobre isso - em vez de corrigir sua implementação para seguir o padrão Unicode mais recente, eles mantêm a versão obsoleta como padrão e as pessoas precisam adicionar "520" para usar a correta agora. E não é compatível com versões anteriores e anteriores, porque você não pode usar a versão "520" nas versões mais antigas do MySQL. Por que eles não podem ter acabado de atualizar seu agrupamento existente? Mesmo com "mb4", realmente. Qual código realmente dependia do antigo comportamento limitado / obsoleto para justificar manter isso como padrão?
thomasrutter
7
Ainda melhor é o padrão de 8.0 utf8mb4_0900_ai_ci.
196 Rick Rick
Respostas:
1591
Esses dois agrupamentos são para a codificação de caracteres UTF-8. As diferenças estão em como o texto é classificado e comparado.
Nota: No MySQL você precisa usar em utf8mb4vez de utf8. Confusamente, utf8é uma implementação falha de UTF-8 das primeiras versões do MySQL que permanece apenas para compatibilidade com versões anteriores. A versão fixa recebeu o nome utf8mb4.
Nota: As versões mais recentes do MySQL atualizam as regras de classificação Unicode, disponíveis sob nomes como utf8mb4_0900_ai_ciregras equivalentes baseadas no Unicode 9.0 - e sem _generalvariante equivalente . As pessoas que estão lendo isso agora provavelmente devem usar um desses agrupamentos mais recentes, em vez de um _unicodeou outro_general . Muito do que está escrito abaixo não é mais de grande interesse se você puder usar um dos agrupamentos mais recentes.
Principais diferenças
utf8mb4_unicode_ci baseia-se nas regras oficiais do Unicode para classificação e comparação universal, que são classificadas com precisão em uma ampla variedade de idiomas.
utf8mb4_general_cié um conjunto simplificado de regras de classificação que tem o objetivo de fazer o melhor possível, além de tomar muitos atalhos projetados para melhorar a velocidade. Ele não segue as regras Unicode e resultará em classificação ou comparação indesejável em algumas situações, como ao usar idiomas ou caracteres específicos.
Em servidores modernos, esse aumento de desempenho será praticamente insignificante. Foi desenvolvido em uma época em que os servidores tinham uma pequena fração do desempenho da CPU dos computadores atuais.
Benefícios de utf8mb4_unicode_cimais deutf8mb4_general_ci
utf8mb4_unicode_ci, que usa as regras Unicode para classificação e comparação, emprega um algoritmo bastante complexo para a classificação correta em uma ampla variedade de idiomas e ao usar uma ampla variedade de caracteres especiais. Essas regras precisam levar em consideração as convenções específicas do idioma; nem todo mundo classifica seus personagens no que chamaríamos de "ordem alfabética".
No que diz respeito às línguas latinas (ou seja, "européias"), não há muita diferença entre a classificação Unicode e a utf8mb4_general_ciclassificação simplificada no MySQL, mas ainda existem algumas diferenças:
Por exemplo, o agrupamento Unicode classifica "ß" como "ss" e "Œ" como "OE" como as pessoas que usavam esses caracteres normalmente desejariam, enquanto os utf8mb4_general_ciclassifica como caracteres únicos (presumivelmente como "s" e "e", respectivamente) .
Alguns caracteres Unicode são definidos como ignoráveis, o que significa que eles não devem contar para a ordem de classificação e a comparação deve passar para o próximo caractere. utf8mb4_unicode_cilida com isso corretamente.
Em idiomas não latinos, como idiomas asiáticos ou com alfabetos diferentes, pode haver muito mais diferenças entre a classificação Unicode e a utf8mb4_general_ciclassificação simplificada . A adequação de utf8mb4_general_cidependerá muito do idioma usado. Para alguns idiomas, será bastante inadequado.
O que você deve usar?
Não há quase nenhuma razão para usar utf8mb4_general_cimais, pois deixamos para trás o ponto em que a velocidade da CPU é baixa o suficiente para que a diferença de desempenho seja importante. Seu banco de dados quase certamente será limitado por outros gargalos além disso.
No passado, algumas pessoas recomendavam o uso, utf8mb4_general_ciexceto quando a classificação precisa seria importante o suficiente para justificar o custo de desempenho. Hoje, esse custo de desempenho praticamente desapareceu e os desenvolvedores estão tratando a internacionalização mais a sério.
Há um argumento a ser argumentado de que, se a velocidade é mais importante para você do que a precisão, você também não pode fazer nenhuma classificação. É trivial tornar um algoritmo mais rápido se você não precisar que seja preciso. Portanto, utf8mb4_general_cié um compromisso que provavelmente não é necessário por motivos de velocidade e provavelmente também não é adequado por motivos de precisão.
Outra coisa a acrescentar é que, mesmo que você saiba que seu aplicativo é compatível apenas com o idioma inglês, ele ainda pode precisar lidar com os nomes das pessoas, que geralmente podem conter caracteres usados em outros idiomas nos quais é tão importante classificar corretamente . O uso das regras Unicode para tudo ajuda a tranqüilizar o fato de que as pessoas Unicode muito inteligentes trabalharam muito para fazer a classificação funcionar corretamente.
O que as partes significam
Em primeiro lugar, cié para classificação e comparação que não diferenciam maiúsculas de minúsculas . Isso significa que é adequado para dados textuais e o caso não é importante. Os outros tipos de intercalação são cs(com distinção entre maiúsculas e minúsculas) para dados de texto onde maiúsculas e minúsculas são importantes e bin, para onde a codificação precisa corresponder, bit por bit, o que é adequado para campos que são realmente dados binários codificados (incluindo, por exemplo, Base64). A classificação com distinção entre maiúsculas e minúsculas leva a alguns resultados estranhos e a comparação com distinção entre maiúsculas e minúsculas pode resultar em valores duplicados que diferem apenas em maiúsculas e minúsculas; portanto, os agrupamentos com diferenciação de maiúsculas e minúsculas estão desvalorizando os dados de texto - se maiúsculas e minúsculas forem importantes para você, pontuação de outra forma ignorável e assim por diante provavelmente também é significativo, e um agrupamento binário pode ser mais apropriado.
A seguir, unicodeou generalrefere-se às regras específicas de classificação e comparação - em particular, a maneira como o texto é normalizado ou comparado. Existem muitos conjuntos diferentes de regras para a codificação de caracteres utf8mb4, com unicodee generalsendo dois que tentam funcionar bem em todos os idiomas possíveis, em vez de um específico. As diferenças entre esses dois conjuntos de regras são o assunto desta resposta. Observe que unicodeusa regras do Unicode 4.0. Versões recentes do MySQL adicionam os conjuntos de regras unicode_520usando regras do Unicode 5.2 e 0900(removendo a parte "unicode_") usando regras do Unicode 9.0.
E, finalmente, utf8mb4é claro que a codificação de caracteres é usada internamente. Nesta resposta, estou falando apenas de codificações baseadas em Unicode.
@KahWeeTeng Você deve nunca mais, nunca use utf8_general_ci: ele simplesmente não funciona. É um retrocesso aos maus e velhos tempos da estagnação ASCII de cinquenta anos atrás. A correspondência que não diferencia maiúsculas de minúsculas de Unicode não pode ser feita sem o mapa de dobras do UCD. Por exemplo, “Σίσυφος” possui três sigmas diferentes; ou como a minúscula de "TSCHüẞ" é "tschüβ", mas a maiúscula de "tschüβ" é "TSCHÜSS". Você pode estar certo ou ser rápido. Portanto, você deve usar utf8_unicode_ci, porque se você não se importa com a correção, é trivial torná-la infinitamente rápida.
tchrist
7
Depois de ler isso, também descobri que utf8_unicode_ci considerará qualquer caractere com o mesmo peso de agrupamento igual para fins de comparação de igualdade. Isso leva a casos em que "か" == "が"ou"ǽ" == "æ" . Para classificar isso faz sentido, mas pode ser surpreendente quando selecionando via igualdades ou lidar com índices únicos - bugs.mysql.com/bug.php?id=16526
Mat Schaffer
4
@DanHorvat A única razão prática para limitar-se ao subconjunto mais antigo e mais limitado do Unicode do MySQL é se você tiver uma versão antiga do MySQL que não suporta o utf8mb4 mais completo. 5.5.3 tem mais de 5 anos. Aprecio que o Plesk seja executado em uma programação diferente do MySQL, mas a maioria das distros está no MySQL 5.5 agora e no Plesk 11.x faz suporte ao MySQL 5.5 se você atualizar seus componentes.
thomasrutter
22
Eu discordaria que o uso da variante mais nova e de reclamação de padrões seja uma prática ruim e acho que é inflamatório chamar as pessoas de desenvolvedores ruins por algo assim. Você também pode notar que minha resposta, como está, diz " em novas versões do MySQL, use utf8mb4, em vez de utf8", enfatizando a minha.
thomasrutter
24
@ DanHorvat utf8mb4é a única opção correta . Com utf8você está preso em alguma variante UTF8 de apenas 3 bytes do MySQL que apenas o MySQL (e o MariaDB) sabem o que fazer. O resto do mundo está usando UTF8, que pode conter até 4 bytes por caractere . Os desenvolvedores do MySQL nomearam incorretamente sua codificação de homebrew utf8e, para não quebrar a compatibilidade com versões anteriores, agora precisam se referir ao UTF8 real como utf8mb4.
Stijn de Witt
162
Eu queria saber qual é a diferença de desempenho entre usar utf8_general_cie utf8_unicode_ci, mas não encontrei nenhum benchmark listado na internet, então decidi criar eu mesmo.
Criei uma tabela muito simples com 500.000 linhas:
CREATETABLE test(
ID INT(11)DEFAULTNULL,
Description VARCHAR(20)DEFAULTNULL)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
Então eu preenchi com dados aleatórios executando este procedimento armazenado:
CREATEPROCEDURE randomizer()BEGINDECLARE i INT DEFAULT0;DECLARE random CHAR(20);
theloop: loop
SET random = CONV(FLOOR(RAND()*99999999999999),20,36);INSERTINTO test VALUES(i+1, random);SET i=i+1;IF i =500000THEN
LEAVE theloop;ENDIF;END LOOP theloop;END
Em seguida, criei os seguintes procedimentos armazenados para fazer benchmark simples SELECT, SELECTcom LIKEe classificação ( SELECTcom ORDER BY):
CREATEPROCEDURE benchmark_simple_select()BEGINDECLARE i INT DEFAULT0;
theloop: loop
SELECT*FROM test
WHERE Description ='test'COLLATE utf8_general_ci;SET i = i +1;IF i =30THEN
LEAVE theloop;ENDIF;END LOOP theloop;END;CREATEPROCEDURE benchmark_select_like()BEGINDECLARE i INT DEFAULT0;
theloop: loop
SELECT*FROM test
WHERE Description LIKE'%test'COLLATE utf8_general_ci;SET i = i +1;IF i =30THEN
LEAVE theloop;ENDIF;END LOOP theloop;END;CREATEPROCEDURE benchmark_order_by()BEGINDECLARE i INT DEFAULT0;
theloop: loop
SELECT*FROM test
WHERE ID > FLOOR(1+ RAND()*(400000-1))ORDERBY Description COLLATE utf8_general_ci LIMIT 1000;SET i = i +1;IF i =10THEN
LEAVE theloop;ENDIF;END LOOP theloop;END;
Nos procedimentos armazenados acima, o utf8_general_ciagrupamento é usado, mas é claro que durante os testes eu usei ambos utf8_general_cie utf8_unicode_ci.
Chamei cada procedimento armazenado 5 vezes para cada agrupamento (5 vezes para utf8_general_cie 5 vezes para utf8_unicode_ci) e depois calculei 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
Nesse benchmark, o uso utf8_unicode_cié mais lento que utf8_general_ciem 3,2%.
benchmark_select_like()
com utf8_general_ci: 11.441 ms
com utf8_unicode_ci: 12.811 ms
Nesse benchmark, o uso utf8_unicode_cié mais lento que utf8_general_ciem 12%.
benchmark_order_by()
com utf8_general_ci : 11.944 ms
com utf8_unicode_ci: 12.887 ms
Nesse benchmark, o uso utf8_unicode_cié mais lento que utf8_general_ciem 7,9%.
Bom benchmark, obrigado por compartilhar. Estou recebendo números sensivelmente semelhantes (MySQL v5.6.12 no Windows): 10%, 4%, 8%. Concordo: o ganho de desempenho utf8_general_cié mínimo demais para valer a pena usar.
randomSeed
10
1) Mas esse benchmark não deve gerar resultados semelhantes para os dois agrupamentos, por definição? Quero dizer, CONV(FLOOR(RAND() * 99999999999999), 20, 36)gera apenas ASCII e nenhum caractere Unicode a ser processado pelos algoritmos dos agrupamentos. 2) Description = 'test' COLLATE ...e Description LIKE 'test%' COLLATE ...processa apenas uma única string ("teste") em tempo de execução, não é? 3) Em aplicativos reais, as colunas usadas na ordenação provavelmente seriam indexadas e a velocidade de indexação em diferentes agrupamentos com texto não-ASCII real pode ser diferente.
Halil Özgür
2
@ HalilÖzgür - seu ponto de vista está parcialmente errado. Eu acho que não é sobre o valor codepoint ser ASCII fora (que general_ci iria lidar corretamente), mas sobre recursos específicos, como o tratamento tremas escritos como "Uml ea ute" ou alguns tais sutilezas.
Em resumo: utf8_unicode_ci usa o algoritmo de agrupamento Unicode, conforme definido nos padrões Unicode, enquanto utf8_general_ci é uma ordem de classificação mais simples, que resulta em resultados de classificação "menos precisos".
obrigado. essa foi a minha impressão. Vou levar o acerto de desempenho :)
onassar
7
Se você não se importa com a correção, é trivial tornar qualquer algoritmo infinitamente rápido. Basta usar utf8_unicode_cie fingir que o outro não existe.
tchrist
1
@tchrist mas se você se preocupa com um certo equilíbrio entre exatidão e velocidade, utf8_general_cipode ser para você
Shelvacu
@tchrist Nunca se tornar um programador de jogos;)
Stijn de Witt
1
@onassar - O MySQL 8.0 afirma ter melhorado significativamente o desempenho de todos os agrupamentos.
Para qualquer conjunto de caracteres Unicode, as operações executadas usando o agrupamento _general_ci são mais rápidas que as do agrupamento _unicode_ci. Por exemplo, as comparações para o agrupamento utf8_general_ci são mais rápidas, mas um pouco menos corretas, do que as comparações para utf8_unicode_ci. A razão para isso é que utf8_unicode_ci suporta mapeamentos como expansões; isto é, quando um caractere é comparado com combinações de outros caracteres. Por exemplo, em alemão e em alguns outros idiomas "ß" é igual a "ss". utf8_unicode_ci também suporta contrações e caracteres ignoráveis. utf8_general_ci é um agrupamento herdado que não suporta expansões, contrações ou caracteres ignoráveis. Ele pode fazer apenas comparações individuais entre os caracteres.
Portanto, para resumir, utf_general_ci usa um conjunto de comparações menor e menos correto (de acordo com o padrão) do que utf_unicode_ci, que deve implementar todo o padrão. O conjunto general_ci será mais rápido porque há menos cálculo a ser feito.
Não existe algo como "um pouco menos correto". A correção é uma característica booleana; não admite modificadores de grau. Basta usar utf8_unicode_cie fingir que a versão quebrada com erros não existe.
22412 tchrist
2
Eu tive problemas ao obter o 5.6.15 para pegar a configuração collation_connection, e você deve passá-la na linha SET, como 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'. O crédito é para Mathias Bynens pela solução, eis o seu guia muito útil: mathiasbynens.be/notes/mysql-utf8mb4
Steve Hibbert
4
@tchrist O problema de dizer que a correção é booleana é que ela não leva em consideração situações que não dependem da correção absoluta. Seu ponto subjacente não é inválido nem estou tentando defender os benefícios do general_ci, mas sua afirmação geral sobre correção é facilmente refutada. Faço isso diariamente em minha profissão. Comédia à parte, Stuart tem um bom argumento aqui .
Anthony
5
Com geolocalização ou desenvolvimento de jogos, trocamos correção com desempenho o tempo todo. E, claro, a correção é um número real entre 0e 1, não um bool. :) Por exemplo, selecionar pontos geográficos em uma caixa delimitadora é uma aproximação de 'pontos próximos', o que não é tão bom quanto calcular a distância entre o ponto e o ponto de referência e filtrá-lo. Mas ambos são uma aproximação e, de fato, a correção total não é alcançável. Veja o paradoxo da costa e o IEEE 754
Stijn de Witt
4
TL; DR : forneça um programa que imprima o resultado correto para:1/3
Stijn de Witt
7
Em poucas palavras:
Se você precisar de uma ordem de classificação melhor - use utf8_unicode_ci(este é o método preferido),
mas se você estiver totalmente interessado em desempenho - use utf8_general_ci, mas saiba que está um pouco desatualizado.
As diferenças em termos de desempenho são muito pequenas.
Ambos estão desatualizados agora - veja a resposta aceita por mais
thomasrutter
OK, obrigado @thomasrutter
simhumileco
6
Alguns detalhes (PL)
Como podemos ler aqui ( Peter Gulutzan ), há uma diferença na classificação / comparação da letra polonesa "Ł" (L com acidente vascular cerebral - html esc:) Ł(letras minúsculas: "ł" - html esc:) ł- temos a 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
Na língua polonesa, a letra Łé depois da letra Le antes M. Ninguém nessa codificação é melhor ou pior - depende de suas necessidades.
utf8[mb4]_unicode_ci
, você pode gostarutf8[mb4]_unicode_520_ci
ainda mais.utf8mb4_0900_ai_ci
.Respostas:
Esses dois agrupamentos são para a codificação de caracteres UTF-8. As diferenças estão em como o texto é classificado e comparado.
Nota: No MySQL você precisa usar em
utf8mb4
vez deutf8
. Confusamente,utf8
é uma implementação falha de UTF-8 das primeiras versões do MySQL que permanece apenas para compatibilidade com versões anteriores. A versão fixa recebeu o nomeutf8mb4
.Nota: As versões mais recentes do MySQL atualizam as regras de classificação Unicode, disponíveis sob nomes como
utf8mb4_0900_ai_ci
regras equivalentes baseadas no Unicode 9.0 - e sem_general
variante equivalente . As pessoas que estão lendo isso agora provavelmente devem usar um desses agrupamentos mais recentes, em vez de um_unicode
ou outro_general
. Muito do que está escrito abaixo não é mais de grande interesse se você puder usar um dos agrupamentos mais recentes.Principais diferenças
utf8mb4_unicode_ci
baseia-se nas regras oficiais do Unicode para classificação e comparação universal, que são classificadas com precisão em uma ampla variedade de idiomas.utf8mb4_general_ci
é um conjunto simplificado de regras de classificação que tem o objetivo de fazer o melhor possível, além de tomar muitos atalhos projetados para melhorar a velocidade. Ele não segue as regras Unicode e resultará em classificação ou comparação indesejável em algumas situações, como ao usar idiomas ou caracteres específicos.Em servidores modernos, esse aumento de desempenho será praticamente insignificante. Foi desenvolvido em uma época em que os servidores tinham uma pequena fração do desempenho da CPU dos computadores atuais.
Benefícios de
utf8mb4_unicode_ci
mais deutf8mb4_general_ci
utf8mb4_unicode_ci
, que usa as regras Unicode para classificação e comparação, emprega um algoritmo bastante complexo para a classificação correta em uma ampla variedade de idiomas e ao usar uma ampla variedade de caracteres especiais. Essas regras precisam levar em consideração as convenções específicas do idioma; nem todo mundo classifica seus personagens no que chamaríamos de "ordem alfabética".No que diz respeito às línguas latinas (ou seja, "européias"), não há muita diferença entre a classificação Unicode e a
utf8mb4_general_ci
classificação simplificada no MySQL, mas ainda existem algumas diferenças:Por exemplo, o agrupamento Unicode classifica "ß" como "ss" e "Œ" como "OE" como as pessoas que usavam esses caracteres normalmente desejariam, enquanto os
utf8mb4_general_ci
classifica como caracteres únicos (presumivelmente como "s" e "e", respectivamente) .Alguns caracteres Unicode são definidos como ignoráveis, o que significa que eles não devem contar para a ordem de classificação e a comparação deve passar para o próximo caractere.
utf8mb4_unicode_ci
lida com isso corretamente.Em idiomas não latinos, como idiomas asiáticos ou com alfabetos diferentes, pode haver muito mais diferenças entre a classificação Unicode e a
utf8mb4_general_ci
classificação simplificada . A adequação deutf8mb4_general_ci
dependerá muito do idioma usado. Para alguns idiomas, será bastante inadequado.O que você deve usar?
Não há quase nenhuma razão para usar
utf8mb4_general_ci
mais, pois deixamos para trás o ponto em que a velocidade da CPU é baixa o suficiente para que a diferença de desempenho seja importante. Seu banco de dados quase certamente será limitado por outros gargalos além disso.No passado, algumas pessoas recomendavam o uso,
utf8mb4_general_ci
exceto quando a classificação precisa seria importante o suficiente para justificar o custo de desempenho. Hoje, esse custo de desempenho praticamente desapareceu e os desenvolvedores estão tratando a internacionalização mais a sério.Há um argumento a ser argumentado de que, se a velocidade é mais importante para você do que a precisão, você também não pode fazer nenhuma classificação. É trivial tornar um algoritmo mais rápido se você não precisar que seja preciso. Portanto,
utf8mb4_general_ci
é um compromisso que provavelmente não é necessário por motivos de velocidade e provavelmente também não é adequado por motivos de precisão.Outra coisa a acrescentar é que, mesmo que você saiba que seu aplicativo é compatível apenas com o idioma inglês, ele ainda pode precisar lidar com os nomes das pessoas, que geralmente podem conter caracteres usados em outros idiomas nos quais é tão importante classificar corretamente . O uso das regras Unicode para tudo ajuda a tranqüilizar o fato de que as pessoas Unicode muito inteligentes trabalharam muito para fazer a classificação funcionar corretamente.
O que as partes significam
Em primeiro lugar,
ci
é para classificação e comparação que não diferenciam maiúsculas de minúsculas . Isso significa que é adequado para dados textuais e o caso não é importante. Os outros tipos de intercalação sãocs
(com distinção entre maiúsculas e minúsculas) para dados de texto onde maiúsculas e minúsculas são importantes ebin
, para onde a codificação precisa corresponder, bit por bit, o que é adequado para campos que são realmente dados binários codificados (incluindo, por exemplo, Base64). A classificação com distinção entre maiúsculas e minúsculas leva a alguns resultados estranhos e a comparação com distinção entre maiúsculas e minúsculas pode resultar em valores duplicados que diferem apenas em maiúsculas e minúsculas; portanto, os agrupamentos com diferenciação de maiúsculas e minúsculas estão desvalorizando os dados de texto - se maiúsculas e minúsculas forem importantes para você, pontuação de outra forma ignorável e assim por diante provavelmente também é significativo, e um agrupamento binário pode ser mais apropriado.A seguir,
unicode
ougeneral
refere-se às regras específicas de classificação e comparação - em particular, a maneira como o texto é normalizado ou comparado. Existem muitos conjuntos diferentes de regras para a codificação de caracteres utf8mb4, comunicode
egeneral
sendo dois que tentam funcionar bem em todos os idiomas possíveis, em vez de um específico. As diferenças entre esses dois conjuntos de regras são o assunto desta resposta. Observe queunicode
usa regras do Unicode 4.0. Versões recentes do MySQL adicionam os conjuntos de regrasunicode_520
usando regras do Unicode 5.2 e0900
(removendo a parte "unicode_") usando regras do Unicode 9.0.E, finalmente,
utf8mb4
é claro que a codificação de caracteres é usada internamente. Nesta resposta, estou falando apenas de codificações baseadas em Unicode.fonte
utf8_general_ci
: ele simplesmente não funciona. É um retrocesso aos maus e velhos tempos da estagnação ASCII de cinquenta anos atrás. A correspondência que não diferencia maiúsculas de minúsculas de Unicode não pode ser feita sem o mapa de dobras do UCD. Por exemplo, “Σίσυφος” possui três sigmas diferentes; ou como a minúscula de "TSCHüẞ" é "tschüβ", mas a maiúscula de "tschüβ" é "TSCHÜSS". Você pode estar certo ou ser rápido. Portanto, você deve usarutf8_unicode_ci
, porque se você não se importa com a correção, é trivial torná-la infinitamente rápida."か" == "が"
ou"ǽ" == "æ"
. Para classificar isso faz sentido, mas pode ser surpreendente quando selecionando via igualdades ou lidar com índices únicos - bugs.mysql.com/bug.php?id=16526utf8mb4
é a única opção correta . Comutf8
você está preso em alguma variante UTF8 de apenas 3 bytes do MySQL que apenas o MySQL (e o MariaDB) sabem o que fazer. O resto do mundo está usando UTF8, que pode conter até 4 bytes por caractere . Os desenvolvedores do MySQL nomearam incorretamente sua codificação de homebrewutf8
e, para não quebrar a compatibilidade com versões anteriores, agora precisam se referir ao UTF8 real comoutf8mb4
.Eu queria saber qual é a diferença de desempenho entre usar
utf8_general_ci
eutf8_unicode_ci
, mas não encontrei nenhum benchmark listado na internet, então decidi criar eu mesmo.Criei uma tabela muito simples com 500.000 linhas:
Então eu preenchi com dados aleatórios executando este procedimento armazenado:
Em seguida, criei os seguintes procedimentos armazenados para fazer benchmark simples
SELECT
,SELECT
comLIKE
e classificação (SELECT
comORDER BY
):Nos procedimentos armazenados acima, o
utf8_general_ci
agrupamento é usado, mas é claro que durante os testes eu usei ambosutf8_general_ci
eutf8_unicode_ci
.Chamei cada procedimento armazenado 5 vezes para cada agrupamento (5 vezes para
utf8_general_ci
e 5 vezes parautf8_unicode_ci
) e depois calculei os valores médios.Meus resultados são:
benchmark_simple_select()
utf8_general_ci
: 9.957 msutf8_unicode_ci
: 10.271 msNesse benchmark, o uso
utf8_unicode_ci
é mais lento queutf8_general_ci
em 3,2%.benchmark_select_like()
utf8_general_ci
: 11.441 msutf8_unicode_ci
: 12.811 msNesse benchmark, o uso
utf8_unicode_ci
é mais lento queutf8_general_ci
em 12%.benchmark_order_by()
utf8_general_ci
: 11.944 msutf8_unicode_ci
: 12.887 msNesse benchmark, o uso
utf8_unicode_ci
é mais lento queutf8_general_ci
em 7,9%.fonte
utf8_general_ci
é mínimo demais para valer a pena usar.CONV(FLOOR(RAND() * 99999999999999), 20, 36)
gera apenas ASCII e nenhum caractere Unicode a ser processado pelos algoritmos dos agrupamentos. 2)Description = 'test' COLLATE ...
eDescription LIKE 'test%' COLLATE ...
processa apenas uma única string ("teste") em tempo de execução, não é? 3) Em aplicativos reais, as colunas usadas na ordenação provavelmente seriam indexadas e a velocidade de indexação em diferentes agrupamentos com texto não-ASCII real pode ser diferente.Esta postagem descreve muito bem.
Em resumo: utf8_unicode_ci usa o algoritmo de agrupamento Unicode, conforme definido nos padrões Unicode, enquanto utf8_general_ci é uma ordem de classificação mais simples, que resulta em resultados de classificação "menos precisos".
fonte
utf8_unicode_ci
e fingir que o outro não existe.utf8_general_ci
pode ser para vocêVeja o manual do mysql, seção Unicode Character Sets :
Portanto, para resumir, utf_general_ci usa um conjunto de comparações menor e menos correto (de acordo com o padrão) do que utf_unicode_ci, que deve implementar todo o padrão. O conjunto general_ci será mais rápido porque há menos cálculo a ser feito.
fonte
utf8_unicode_ci
e fingir que a versão quebrada com erros não existe.0
e1
, não um bool. :) Por exemplo, selecionar pontos geográficos em uma caixa delimitadora é uma aproximação de 'pontos próximos', o que não é tão bom quanto calcular a distância entre o ponto e o ponto de referência e filtrá-lo. Mas ambos são uma aproximação e, de fato, a correção total não é alcançável. Veja o paradoxo da costa e o IEEE 7541/3
Em poucas palavras:
Se você precisar de uma ordem de classificação melhor - use
utf8_unicode_ci
(este é o método preferido),mas se você estiver totalmente interessado em desempenho - use
utf8_general_ci
, mas saiba que está um pouco desatualizado.As diferenças em termos de desempenho são muito pequenas.
fonte
Alguns detalhes (PL)
Como podemos ler aqui ( Peter Gulutzan ), há uma diferença na classificação / comparação da letra polonesa "Ł" (L com acidente vascular cerebral - html esc:)
Ł
(letras minúsculas: "ł" - html esc:)ł
- temos a seguinte suposição:Na língua polonesa, a letra
Ł
é depois da letraL
e antesM
. Ninguém nessa codificação é melhor ou pior - depende de suas necessidades.fonte
Há duas grandes diferenças na classificação e na correspondência de caracteres:
Classificação :
utf8mb4_general_ci
remove todos os acentos e classificações, uma por uma, o que pode criar resultados de classificação incorretos.utf8mb4_unicode_ci
classifica preciso.Correspondência de caracteres
Eles combinam caracteres de maneira diferente.
Por exemplo,
utf8mb4_unicode_ci
você temi != ı
, masutf8mb4_general_ci
mantémı=i
.Por exemplo, imagine que você tem uma briga com
name="Yılmaz"
. Entãoretornaria a linha se a colocação for
utf8mb4_general_ci
, mas se for colocada comutf8mb4_unicode_ci
ela, não retornará a linha!Por outro lado, temos isso
a=ª
eß=ss
emutf8mb4_unicode_ci
que não é o casoutf8mb4_general_ci
. Imagine que você tem uma briga comname="ªßi"
, entãoretornaria a linha se a colocação for
utf8mb4_unicode_ci
, mas não retornaria uma linha se a colocação estiver definida comoutf8mb4_general_ci
.Uma lista completa de correspondências para cada colocação pode ser encontrada aqui .
fonte
De acordo com este post, há um benefício de desempenho consideravelmente grande no MySQL 5.7 ao usar utf8mb4_general_ci em vez de utf8mb4_unicode_ci: https://www.percona.com/blog/2019/02/27/charset-and-collation-settings-impact -on-mysql-performance /
fonte