Há desvantagens em usar um varchar genérico (255) para todos os campos baseados em texto?

Eu tenho uma tabela de contacts que contém campos como postcode , first name , last name , town , country , phone number etc, todos os quais são definidos como VARCHAR(255) , embora nenhum desses campos nunca chegará perto de ter 255 caracteres . (Se você está se perguntando, é assim porque migrações Ruby on Rails mapeiam campos String para VARCHAR(255) por padrão e eu nunca me preocupei em sobrescrevê-lo).

Como o VARCHAR armazenará apenas o número de caracteres reais do campo (juntamente com o comprimento do campo), existe alguma vantagem distinta (desempenho ou não) em usar, digamos, VARCHAR(16) sobre VARCHAR(255) ?

Além disso, a maioria desses campos possui índices neles. Um tamanho VARCHAR maior no campo afeta o tamanho ou o desempenho do índice?

FYI eu estou usando o MySQL 5.

No armazenamento, VARCHAR(255) é inteligente o suficiente para armazenar apenas o comprimento que você precisa em uma determinada linha, ao contrário de CHAR(255) que sempre armazena 255 caracteres.

Mas desde que você marcou essa questão com o MySQL, mencionarei uma dica específica do MySQL: conforme as linhas são copiadas da camada do mecanismo de armazenamento para a camada SQL, os campos VARCHAR são convertidos em CHAR para obter a vantagem de trabalhar com linhas de largura fixa. . Assim, as strings na memory são preenchidas com o comprimento máximo da coluna VARCHAR declarada.

Quando sua consulta gera implicitamente uma tabela temporária, por exemplo, durante a sorting ou GROUP BY , isso pode usar muita memory. Se você usar muitos campos VARCHAR(255) para dados que não precisam ser tão longos, isso pode tornar a tabela temporária muito grande.

Você também pode gostar de saber que esse comportamento “padding out” significa que uma string declarada com o conjunto de caracteres utf8 é preenchida com três bytes por caractere, mesmo para strings armazenadas com conteúdo de byte único (por exemplo, caracteres ascii ou latin1). Da mesma forma, o conjunto de caracteres utf8mb4 faz com que a cadeia seja preenchida com quatro bytes por caractere na memory.

Portanto, um VARCHAR(255) em utf8 armazenando uma cadeia curta como “Sem opinião” leva 11 bytes no disco (dez caracteres de charset mais baixo, mais um byte para comprimento) mas leva 765 bytes na memory e, portanto, em tabelas temporárias ou classificadas resultados.

Eu ajudei os usuários do MySQL que inadvertidamente criaram tabelas temporárias de 1,5 GB com frequência e preencheram seu espaço em disco. Eles tinham muitas colunas VARCHAR(255) que, na prática, armazenavam strings muito curtas.

É melhor definir a coluna com base no tipo de dados que você pretende armazenar. Ele tem benefícios para impor restrições relacionadas a aplicativos, como outras pessoas mencionaram. Mas tem os benefícios físicos para evitar o desperdício de memory que descrevi acima.

É difícil saber qual é o endereço postal mais longo, é claro, e é por isso que muitas pessoas escolhem um VARCHAR longo que é certamente mais longo do que qualquer endereço. E 255 é habitual porque é o comprimento máximo de um VARCHAR para o qual o comprimento pode ser codificado com um byte. Foi também o comprimento máximo do VARCHAR no MySQL mais antigo que 5.0.

Além das considerações de tamanho e desempenho de definir o tamanho de um varchar (e possivelmente mais importante, como armazenamento e processamento ficam mais baratos a cada segundo), a desvantagem de usar varchar (255) “apenas porque” é a integridade de dados reduzida.

Definir limites máximos para strings é uma boa coisa a ser feita para evitar que strings mais longas do que o esperado entrem no RDBMS e causem saturações de buffer ou exceções / erros posteriormente ao recuperar e analisar valores do database que são mais longos (mais bytes) do que o esperado.

Por exemplo, se você tiver um campo que aceita cadeias de caracteres de dois caracteres para abreviações de países, não há razão concebível para esperar que seus usuários (nesse contexto, programadores) insiram nomes completos de país. Como você não quer que eles digitem “Antigua and Barbuda” (AG) ou “Heard Island e McDonald Islands” (HM), você não permite isso na camada de database. Além disso, é provável que alguns programadores ainda não tenham RTFMed a documentação de design ( que certamente existe ) para saber não fazer isso.

Defina o campo para aceitar dois caracteres e deixar o RDBMS lidar com ele (seja graciosamente, truncar ou desagradadamente, rejeitando seu SQL com um erro).

Exemplos de dados reais que não têm razão para exceder um determinado comprimento:

  • Os códigos postais canadenses são do formato A1A1A1 e têm sempre 6 caracteres, mesmo para o Papai Noel (6 caracteres exclui o espaço que pode ser especificado para legibilidade).
  • endereços de e-mail – até 64 bytes antes do @, até 255 bytes depois. Nunca mais, para que você não quebre a Internet.
  • Os números de telefone norte-americanos nunca têm mais de 10 dígitos (excluindo o código do país).
  • Computadores em execução (versões recentes do) O Windows não pode ter nomes de computador com mais de 63 bytes , embora mais de 15 não seja recomendado e irá interromper o farm de servidores do Windows NT.
  • Abreviações de estado são 2 caracteres (como os códigos de país exampled acima)
  • Os números de rastreamento da UPS têm 18, 12, 11 ou 9 caracteres. Os números de 18 caracteres começam com “1Z” e os números de 11 caracteres começam com “T”, o que faz você se perguntar como eles entregam todos esses pacotes se eles não sabem a diferença entre letras e números.

E assim por diante…

Aproveite o tempo para pensar sobre seus dados e seus limites. Se você é arquiteto, desenvolvedor ou programador, é o seu trabalho , afinal.

Usando um varchar (n) em vez de varchar (255), você elimina o problema em que os usuários (usuários finais, programadores, outros programas) inserem dados inesperadamente longos que voltarão para assombrar seu código posteriormente.

E eu não disse que você não deveria implementar essa restrição no código de lógica de negócios usado pelo seu aplicativo.

Estou contigo. Fussy atenção aos detalhes é uma dor no pescoço e tem valor limitado.

Era uma vez, o disco era um bem precioso e costumávamos suar as balas para otimizá-lo. O preço do armazenamento caiu por um fator de 1.000, tornando o tempo gasto em apertar cada byte menos valioso.

Se você usar apenas campos CHAR, poderá obter linhas de comprimento fixo. Isso pode economizar um pouco de disco real se você escolher tamanhos precisos para campos. Você pode obter dados mais densos (menos E / Ss para varreduras de tabela) e atualizações mais rápidas (mais fácil de localizar espaços abertos em um bloco para atualizações e inserções).

No entanto, se você superestimar seus tamanhos ou seus tamanhos reais de dados forem variables, você acabará desperdiçando espaço com os campos CHAR. Os dados serão encerrados com menos densidade (levando a mais I / O para grandes recuperações).

Geralmente, os benefícios de desempenho da tentativa de colocar um tamanho em campos variables ​​são menores. Você pode facilmente comparar usando VARCHAR (255) comparado com CHAR (x) para ver se você pode medir a diferença.

No entanto, às vezes, preciso fornecer uma dica “pequena”, “média” e “grande”. Então eu uso 16, 64 e 255 para os tamanhos.

Hoje em dia, não consigo imaginar que isso realmente importe mais.

Há uma sobrecarga computacional para usar campos de comprimento variável, mas com os excessos de CPUs hoje, não vale a pena considerar. O sistema de E / S é tão lento a ponto de fazer com que quaisquer custos computacionais manipulem varchars efetivamente inexistentes. Na verdade, o preço de um varchar computacionalmente é provavelmente uma vitória líquida sobre a quantidade de espaço em disco salvo usando campos de comprimento variável em campos de comprimento fixo. Você provavelmente tem maior densidade de linhas.

Agora, a complexidade dos campos varchar é que você não pode localizar facilmente um registro através de seu número de registro. Quando você tem um tamanho de linha de comprimento fixo (com campos de comprimento fixo), é trivial calcular o bloco de disco para o qual um id de linha aponta. Com um tamanho de linha de comprimento variável, esse tipo de sai pela janela.

Portanto, agora você precisa manter algum tipo de índice de número de registro, assim como qualquer outra chave primária, OU você precisa criar um identificador de linha robusto que codifique os detalhes (como o bloco etc.) no identificador. Se você fizer isso, no entanto, o id teria que ser recalculado se a linha for movida no armazenamento persistente. Não é grande coisa, só precisa rewrite todas as inputs de índice e certifique-se de que você a) nunca exponha ao consumidor ou b) nunca afirme que o número é confiável.

Mas como temos campos varchar hoje, o único valor de varchar (16) sobre varchar (255) é que o database aplicará o limite de 16 caracteres no varchar (16). Se o modelo de database é, na verdade, representativo do modelo de dados físico, então, ter comprimentos de campos pode ser valioso. Se, no entanto, é simplesmente “armazenamento” em vez de “modelo AND armazenamento”, não há necessidade alguma.

Então você simplesmente precisa discernir entre um campo de texto que é indexável (como varchar) versus algo que não é (como um campo de texto ou CLOB). Os campos indexáveis ​​tendem a ter um limite no tamanho para facilitar o índice, enquanto os campos CLOB não (dentro da razão).

Na minha experiência, se você permitir um tipo de dados de 255 caracteres, algum usuário estúpido (ou algum testador experiente) realmente preencherá isso.

Então você tem todos os tipos de problemas, incluindo quanto espaço você permite para esses campos em relatórios e exibições na canvas em seu aplicativo. Sem mencionar a possibilidade de exceder o limite por linha de dados em seu database (se você tivesse mais que alguns desses campos de 255 caracteres).

É muito mais fácil escolher um limite razoável no início e, em seguida, impor isso por meio do aplicativo e do database.

É uma boa prática alocar um pouco mais do que você precisa. Números de telefone nunca seriam tão grandes.

Uma razão é que, a menos que você valide contra inputs grandes, sem dúvida alguém usará tudo o que houver. Então você pode ficar sem espaço na sua linha. Não tenho certeza sobre o limite do MySQL, mas o 8060 é o tamanho de linha máximo no MS SQL.

Um padrão mais normal seria 50 imho e, em seguida, aumentar onde for necessário.

Em um contexto mysql, ele pode ser importante ao trabalhar com índices nas referidas colunas varchar, já que o mysql tem um max. limite de 767 bytes por linha de índice.

Isto significa que ao adicionar um índice através de várias colunas varchar 255, você pode chegar a este limite rapidamente / até mais rápido nas colunas utf8 ou utf8mb4, como indicado nas respostas acima.