UTF-8: Geral? Bin? Unicode?

279

Estou tentando descobrir qual agrupamento devo usar para vários tipos de dados. 100% do conteúdo que armazenarei é enviado pelo usuário.

Meu entendimento é que eu deveria usar o IC geral UTF-8 (sem distinção entre maiúsculas e minúsculas) em vez do binário UTF-8. No entanto, não consigo encontrar uma distinção clara entre o IC geral UTF-8 e o IC Unicode UTF-8.

  1. Devo estar armazenando o conteúdo enviado pelo usuário nas colunas UTF-8 General ou UTF-8 Unicode CI?
  2. A que tipo de dados o UTF-8 Binary se aplica?
Dolph
fonte
16
Nota lateral, mas em vez de utf8, use em utf8mb4vez disso para suporte total ao UTF-8. Comentando aqui porque as respostas sobre essa pergunta popular não abordam isso. mathiasbynens.be/notes/mysql-utf8mb4
Steven R. Loomis
Se você deseja dobrar maiúsculas e minúsculas, mas com sensibilidade ao sotaque, envie uma solicitação em bugs.mysql.com .
Rick James
Ou clique em "Me afeta" em bugs.mysql.com/bug.php?id=58797 e adicione um comentário.
21717 Rick

Respostas:

299

Em geral, utf8_general_ci é mais rápido que utf8_unicode_ci , mas menos correto.

Aqui está a diferença:

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 legado que não suporta expansões, contrações ou caracteres ignoráveis. Ele pode fazer apenas comparações individuais entre os caracteres.

Citado em: http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

Para uma explicação mais detalhada, leia a seguinte publicação nos fóruns do MySQL: http://forums.mysql.com/read.php?103,187048,188748

Quanto ao utf8_bin: utf8_general_ci e utf8_unicode_ci executam uma comparação que não diferencia maiúsculas de minúsculas. Em contraste, utf8_bin faz distinção entre maiúsculas e minúsculas (entre outras diferenças), porque compara os valores binários dos caracteres.

Sagi
fonte
2
Eu acho que se você não tiver um bom motivo para usar _unicode_ci, use _general_ci.
Sagi
4
Isso realmente não responde à pergunta em profundidade. Qual é a diferença entre essas agrupações exatamente?
Pekka
4
Você está certo, a diferença exata não é fornecida aqui por uma questão de simplicidade. Adicionei um link a uma postagem com a diferença exata .
Sagi
Nota: show collation;você pode ver o agrupamento padrão para cada conjunto de caracteres. 5.1 mostra utf8_general_cicomo padrão para utf8.
David Carboni
9
Existem recursos que aprofundariam a diferença de velocidade real entre os dois agrupamentos? Estamos falando de uma queda de 0,1% no desempenho ou de 10%?
Emphram Stavanger
90

Você também deve estar ciente do fato de que, com utf8_general_ci ao usar um campo varchar como índice exclusivo ou primário, inserir 2 valores como 'a' e 'á' causaria um erro de chave duplicado.

Alex Hepp
fonte
3
Obrigado, isso é útil para evitar nomes de usuário semelhantes (por exemplo, se "jose" existir, eu não gostaria que outra pessoa criasse um usuário "josé"). NB: isso também é válido para a maioria dos agrupamentos utf8 (exceto utf8_bin). O mais seguro / seguro / mais abrangente éutf8_unicode_ci
Costa
2
Eu uso utf8_bin onde quero que jose e josé sejam distinguidos no índice. Por exemplo, uma coluna que registra operações de pesquisa / substituição, em que o usuário pode ter decidido procurar por josé e substituí-lo por jose. (Eu estou escrevendo um programa de planilha)
Buttle Butkus
33
  • utf8_bincompara os bits cegamente. Nenhuma caixa dobrável, sem sotaque.
  • utf8_general_cicompara um byte com um byte. Faz caso dobrável e remoção de sotaque, mas nenhuma comparação de dois caracteres: ijnão é igual ijneste agrupamento.
  • utf8_*_cié um conjunto de regras específicas do idioma, mas de outro modo semelhante unicode_ci. Alguns casos especiais: Ç,Č , ch,ll
  • utf8_unicode_ci segue um antigo padrão Unicode para comparações. ij= ij, mas ae! =æ
  • utf8_unicode_520_ci segue um padrão Unicode mais recente. ae=æ

Vejo tabela de agrupamentos para obter detalhes sobre o que é igual ao que em vários agrupamentos utf8.

utf8, conforme definido pelo MySQL, é limitado aos códigos utf8 de 1 a 3 bytes. Isso deixa Emoji e alguns chineses. Então você deve realmente mudar para utf8mb4se quiser ir muito além da Europa.

Os pontos acima se aplicam a utf8mb4 , após a alteração ortográfica adequada. No futuro, utf8mb4e utf8mb4_unicode_520_cisão os preferidos.

  • utf16 e utf32 são variantes no utf8; não há praticamente nenhum uso para eles.
  • O ucs2 está mais próximo de "Unicode" que de "utf8"; praticamente não há utilidade para isso.
Rick James
fonte
1
Re "fique atento": os agrupamentos 8.0 mostram como vários caracteres, ditongos etc. se comparam nos agrupamentos 8.0 utf8mb4; O utf8 é basicamente o mesmo.
Rick James
E as intercalações 8.0 são marcadas como sendo significativamente mais rápidas que a 5.x.
Rick James
seria bom se essa página listasse utf8mb4_bin na parte superior. Eu sei que ele não corresponde a nenhum personagem, mas é bom para iniciantes.
Henk Poley
6

Realmente, testei salvar valores como 'é' e 'e' na coluna com valores únicos índice e eles causam erros duplicados em 'utf8_unicode_ci' e 'utf8_general_ci'. Você pode salvá-los somente na coluna intercalada 'utf8_bin'.

E os documentos do mysql (em http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html ) sugerem em seus exemplos o conjunto 'utf8_general_ci'.

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
vitalii
fonte
1
Eu fiz um teste rápido sobre isso, e parece ser preciso. Ambos os agrupamentos se comportam da mesma maneira quando se trata de uma chave exclusiva em uma coluna e valores com tildes e similares.
MirroredFate
@MirroredFate OK, devo adicionar lá essa coluna deve ter um índice exclusivo para causar esse erro. Isso implica na minha resposta.
vitalii 01/07/2015
3

A resposta aceita está desatualizada.

Se você usa o MySQL 5.5.3+, use em utf8mb4_unicode_civez de utf8_unicode_cipara garantir que os caracteres digitados pelos usuários não apresentem erros.

utf8mb4suporta emojis, por exemplo, enquanto utf8pode oferecer centenas de bugs relacionados à codificação, como:

Incorrect string value: ‘\xF0\x9F\x98\x81…’ for column ‘data’ at row 1

Marwann
fonte
Esta resposta (corretamente) soluciona problemas com a codificação de Emoji (e alguns em chinês). Mas a questão parece estar focada no agrupamento. utf8mb4_unicode_citrata (eu acho) todos os Emoji iguais. utf8mb4_unicode_520_cidá um pedido a Emoji.
Rick James