Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Comprimento do índice varchar do MySQL


Edição de setembro de 2021:Estou usando o MySQL 8.0 há alguns anos, então aqui estão algumas informações atualizadas.

O manual do MySQL agora tem uma página muito informativa sobre a conversão entre utf8mb3 (atualmente também conhecido como utf8 ) e utf8mb4 . utf8mb3 está obsoleto e será removido eventualmente; e quando é removido, seu alias atual, utf8 , fará referência a utf8mb4 em vez de.

Com utf8mb3 obsoleto , você pode armazenar até 255 caracteres em um índice, enquanto com utf8mb4 , até 191, ao usar COMPACT ou REDUNDANT formato de linha.

Com COMPRESSED ou DYNAMIC formato de linha, os prefixos de chave de índice podem ter até 3072 bytes. Com eles, você pode indexar até 1024 caracteres para utf8mb3 , e 768 caracteres para utf8mb4 .

Abaixo está minha resposta anterior, que explica parte da lógica por trás do número de caracteres você pode indexar em relação ao número de bytes .

Devo revisar minha resposta devido à minha pesquisa. Eu postei originalmente isso (me citando):

Eu acredito que a resposta é que você não pode saber quantos caracteres estarão no índice porque você não pode saber quantos bytes seus caracteres serão (a menos que você faça algo para excluir caracteres multi-byte).

E eu não tenho certeza, mas ainda pode estar correto, mas não da maneira que eu estava pensando.

Aqui está a resposta correta:

O MySQL assume 3 bytes por caractere utf8. 255 caracteres é o tamanho máximo de índice que você pode especificar por coluna, pois 256x3=768, o que quebra o limite de 767 bytes.

Se você não especificar o tamanho do índice, o MySQL escolhe o tamanho máximo (ou seja, 255 por coluna). Uma restrição UNIQUE não pode ser colocada em uma coluna utf8 cujo comprimento seja maior que 255, porque um índice único deve conter o valor da célula inteira. Mas um índice regular pode ser usado - ele apenas indexará os primeiros 255 caracteres (ou os primeiros 767 bytes?). E é aí que ainda há algum mistério para mim.

O Mistério:Eu posso ver porque o MySQL assume 3 bytes por caractere, por segurança, porque senão a restrição UNIQUE pode ser quebrada. Mas os documentos parecem sugerir que o índice é realmente dimensionado em bytes, não em caracteres. Então, suponha que você coloque 255 char (765 bytes) índice em um varchar(256 ) coluna. Se os caracteres armazenados forem todos ASCII, caracteres de 1 byte, como A-Z, a-z, 0-9, então você poderá ajustar a coluna inteira no índice de 767 bytes. E parece que é isso que realmente aconteceria.

Abaixo estão mais algumas informações da minha resposta original sobre caracteres, bytes etc.

De acordo com a wikipedia , o caractere UTF-8 pode ter 1,2, 3 ou 4 bytes. Mas, de acordo com esta documentação do mysql , o tamanho máximo do caractere é de 3 bytes e, portanto, qualquer índice de índice de coluna com mais de 255 caracteres pode atingir esse limite de bytes. Mas pelo que entendi, pode não ser. Se a maioria dos seus caracteres estiver no intervalo ASCII, o tamanho médio dos caracteres será mais próximo de 1 byte. Se o tamanho médio dos caracteres for, por exemplo, 1,3 bytes (principalmente 1 byte, mas um número significativo de caracteres de 2 a 3 bytes), você poderá especificar um índice de 767/1,3

Portanto, se você estiver armazenando principalmente caracteres de 1 byte, seu limite real de caracteres seria mais como:767 / 1,3 =590. Mas acontece que não é assim que funciona. 255 caracteres é o limite.

Conforme mencionado em esta documentação do MySQL ,

Os limites de prefixo são medidos em bytes, enquanto o comprimento do prefixo nas instruções CREATE INDEX é interpretado como número de caracteres para tipos de dados não binários (CHAR, VARCHAR, TEXT). Leve isso em consideração ao especificar um comprimento de prefixo para uma coluna que usa um conjunto de caracteres multibyte.

Parece que o MySQL está aconselhando as pessoas a fazer um cálculo/guestimation como acabei de fazer para determinar o tamanho da chave para uma coluna varchar. Mas na verdade você não pode especifique um índice maior que 255 para colunas utf8.

Finalmente, se você voltar ao meu segundo link novamente, também há isso:

Quando a opção de configuração innodb_large_prefix está habilitada, esse limite de comprimento é aumentado para 3072 bytes, para tabelas InnoDB que usam os formatos de linha DYNAMIC e COMPRESSED.

Portanto, parece que você pode obter índices muito maiores, se quiser, com alguns ajustes. Apenas certifique-se de que os formatos de linha sejam DYNAMIC ou COMPRESSED. Você provavelmente pode especificar um índice de 1023 ou 1024 caracteres nesse caso.
A propósito, você pode armazenar caracteres de 4 bytes usando [o conjunto de caracteres utf8mb4][4]. O conjunto de caracteres utf8 aparentemente armazena apenas [caracteres do "plano 0"][5].
EDITAR:

Acabei de tentar criar um índice composto em uma coluna varchar(511) com uma coluna tinyint(1) e recebi a mensagem de erro dizendo que o tamanho máximo do índice era 767 bytes. Isso me faz acreditar que o MySQL assume que as colunas do conjunto de caracteres utf8 conterão 3 bytes por caractere (o máximo) e permite que você use 255 caracteres no máximo. Mas talvez isso seja apenas com índices compostos. Atualizarei minha resposta à medida que descobrir mais. Mas por enquanto estou deixando isso como uma edição.