Eu tenho uma coluna indexada que armazena um hash MD5. Assim, a coluna sempre armazenará um valor de 32 caracteres. Por qualquer motivo, isso foi criado como um varchar em vez de um char. Vale a pena migrar o banco de dados para convertê-lo em um caractere? Isso está no MySQL 5.0 com InnoDB.
mysql
performance
innodb
varchar
Jason Baker
fonte
fonte
Respostas:
Uma pergunta semelhante foi feita antes
Implicações de desempenho dos tamanhos MySQL VARCHAR
Aqui está o trecho da minha resposta
Você deve perceber as vantagens e desvantagens de usar CHAR vs VARCHAR
Com os campos CHAR, o que você aloca é exatamente o que recebe. Por exemplo, CHAR (15) aloca e armazena 15 bytes, independentemente de como você coloca os caracteres no campo. A manipulação de strings é simples e direta, pois o tamanho do campo de dados é totalmente previsível.
Com os campos VARCHAR, você obtém uma história completamente diferente. Por exemplo, o VARCHAR (15) na verdade aloca dinamicamente até 16 bytes, até 15 para dados e, pelo menos, 1 byte adicional para armazenar o comprimento dos dados. Se você tiver a string 'hello' para armazenar que terá 6 bytes, não 5. A manipulação da string sempre deve executar alguma forma de verificação de comprimento em todos os casos.
A troca é mais evidente quando você faz duas coisas: 1. Armazenando milhões ou bilhões de linhas 2. Colunas de indexação que são CHAR ou VARCHAR
TRADEOFF # 1 Obviamente, o VARCHAR possui a vantagem, já que dados de comprimento variável produziriam linhas menores e, portanto, arquivos físicos menores.
TRADEOFF # 2 Como os campos CHAR exigem menos manipulação de sequência devido às larguras fixas, as pesquisas de índice no campo CHAR são, em média, 20% mais rápidas que as dos campos VARCHAR. Esta não é nenhuma conjectura da minha parte. O livro MySQL Database Design and Tuning executou algo maravilhoso em uma tabela MyISAM para provar isso. O exemplo no livro fez algo como o seguinte:
Esta diretiva força todos os VARCHARs a se comportarem como CHARs. Eu fiz isso no meu trabalho anterior em 2007 e peguei uma tabela de 300 GB e acelerou as pesquisas de índice em 20%, sem alterar mais nada. Funcionou como publicado. No entanto, produziu uma tabela com quase o dobro de tamanho, mas isso simplesmente remonta ao tradeoff # 1.
Você pode analisar os dados armazenados para ver o que o MySQL recomenda para a definição de colunas. Basta executar o seguinte em qualquer tabela:
Isso percorrerá a tabela inteira e recomendará definições de coluna para cada coluna com base nos dados que ela contém, nos valores mínimos de campo, no máximo e em outros itens. Às vezes, você só precisa usar o bom senso ao planejar CHAR vs VARCHAR. Aqui está um bom exemplo:
Se você estiver armazenando endereços IP, a máscara para essa coluna terá no máximo 15 caracteres (xxx.xxx.xxx.xxx). Eu pularia imediatamente,
CHAR(15)
porque os comprimentos dos endereços IP não variariam muito e a complexidade adicional da manipulação de strings controlada por um byte adicional. Você ainda pode fazer umPROCEDURE ANALYSE()
contra essa coluna. Pode até recomendar o VARCHAR. Meu dinheiro ainda estaria em CHAR sobre VARCHAR nesse caso.Os problemas CHAR x VARCHAR podem ser resolvidos apenas através do planejamento adequado. Com grande poder vem uma grande responsabilidade (clichê, mas é verdade).
ATUALIZAR
Quando se trata do MD5, o cálculo
strlen
interno deve ser eliminado ao alternar todo o formato da linha. Não seria necessário alterar a definição do campo.Se a chave MD5 for o único VARCHAR presente, eu a utilizaria e converteria o formato da linha da tabela em fixo . Se houver um número significativo de outros campos VARCHAR presentes, eles também serão beneficiados. Em troca, a tabela seria expandida para aproximadamente o dobro do seu tamanho. Mas as consultas devem acelerar cerca de 20% a mais sem ajuste adicional.
fonte
bit
ebinary
?Parece que você economizará 1 byte por valor ou cerca de 3% convertendo para a
char
. Provavelmente não vale a pena se você estiver armazenando o MD5 em hexadecimal de qualquer maneira - você pode economizar 50% usando umbinary
.Agradecemos a Ovais (veja comentários) por apontar que
char(32)
pode usar muito mais do que 32 bytes se você estiver usando um conjunto de caracteres multibyte.Agradecemos a Rick James por indicar que você deve usar a
unhex
função para converter a string hexadecimal em binária:db <> mexer aqui
fonte
binary
- ou eu entendi errado?BINARY
faz muito pouco, a menos que você também useUNHEX()
. Ou seja, você pode armazenarUNHEX(MD5(x))
em um 16-byteBINARY(16)
para economizar espaço significativa sobre o armazenamentoMD5(x)
emCHAR(32) CHARACTER SET ascii
.Não vale a pena mudar na minha opinião. Se você examinar a documentação aqui, ela deve ilustrar a diferença entre os dois. No cenário de uso, um não oferece realmente nenhum benefício significativo sobre o outro, a menos que você esteja realmente preocupado com a sobrecarga extra relacionada ao tamanho da linha.
http://dev.mysql.com/doc/refman/5.0/en/char.html
Observe também o primeiro comentário na documentação que eu vinculo acima ... "O CHAR só acelerará o seu acesso se todo o registro tiver tamanho fixo. Ou seja, se você usar qualquer objeto de tamanho variável, é possível fazer todos eles tamanho da variável. Você não ganha velocidade usando um CHAR em uma tabela que também contém um VARCHAR "
fonte