Skip to content

Varchar ou não varchar? Eis a questão

14/10/2009

Aprender a usar sistemas gerenciadores de banco de dados não é uma coisa tão difícil. De longe parece um bicho de sete cabeças, mas depois que você olha mais de perto percebe que na verdade ele é só um bicho de sete tabelas. Você vai colocando um campo aqui, um outro ali, cria meia dúzia de chaves primárias, uma dúzia de chaves estrangeiras e está pronta a estrutura básica do seu banco.

Por mais increça que parível, uma das etapas mais simples é a que me deixa com mais dúvidas: definir o tamanho dos campos. Assim como quando se está programando em uma linguagem qualquer, cada tipo de variável tem um tamanho máximo e você pode especificar que quer usar um tamanho menor e assim reduzir o desperdício de memória no seu programa.

O tipo varchar, que ilustra o título deste artigo, armazena 65536 (2^16) bytes de caracteres, o que para armazenar o nome de uma pessoa é muito, ao passo que quando estamos falando de textos extensos esse limite pode ser facilmente superado. Um link de blog, por exemplo, possui em média uns 100 caracteres. Resolvido, varchar de 100, certo? Nada! Há relatos de URL’s com 2063 caracteres. Este site “encompridor” de URL’s gera links com mais de 3600 caracteres, e o pior, que funcionam em quase todos os browsers! Só não funcionam no Internet Explorer, que tem uma limitação de 2083 caracteres para URL’s.

O fato é que quando padronizaram o URI e o URL esqueceram de definir um tamanho máximo para essas strings. E aí? Como nós, desenvolvedores, ficamos? Que tamanho eu coloco no varchar? Se eu colocar um tamanho razoável eu corro o risco de perder informações, se eu colocar o tamanho máximo eu desperdiço espaço e aumentam os custos com hospedagem, sem falar na questão do desempenho.

Por não saber o que fazer, fui olhar o que o WordPress fez, afinal milhares de blogueiros ao redor do mundo que tiram seu sustento dessa plataforma devem ter algum motivo para usá-la. Das duas uma: ou esses blogueiros não entendem nada de banco de dados ou eu estou deixando de considerar alguma informação importante, porque quando vi os campos das tabelas tomei um susto: o título dos posts do WordPress é do tipo text, o equivalente a (imagine) 65536 bytes, na pior das hipóteses 65536 caracteres!

O campo do conteúdo do post então é outro absurdo: longtext, traduzindo, 4MB, mais de 4 milhões de caracteres! Isso é 405.000 vezes maior do que o review enorme que o Keaton fez sobre sua multifuncional! Ao que parece o banco do Drupal deve ser mais enxuto, pois no começo de 2008 alguns usuários relataram problemas ao assinar feeds com URL’s maiores que 255 caracteres.

Recebi sugestões de usar varchar de 3000 caracteres, e até cogitei a solução que deram no caso do Drupal: usar a API do TinyURL para os links mais insanos, fazendo isso de forma transparente para o usuário. Mas aí entra outra questão: depender de um serviço como o TinyURL não diminuiria a confiabilidade da minha aplicação? Vale a pena criar um encurtador de URL’s próprio? Será que o MySQL possui algum tipo de compactação para os tipos text e longtext? Qual a sua opinião sobre o assunto? Qual a resposta para a vida, o universo e tudo mais? O que o Mr. Pink fez com a maleta?

UPDATE: o var de varchar simboliza que este tipo tem tamanho variável. Enquanto char(10) ocupa exatamente 10 bytes, um varchar(10) ocupa a quantidade de caracteres usados mais 1 byte pra gravar essa quantidade. No entanto, o tamanho máximo de um índice no MySQL é +/- 760 bytes, logo é impossível usar um varchar(3000) como chave, seja primária, única, estrangeira, o escambau.

Já os tipos text seguem a mesma filosofia do varchar de só ocupar quanto espaço for necessário, mas esses tipos ficam gravados meio que fora do registro, em um local separado, e o que vai na tabela é uma referência para esse local. Quanto maior o text (longtext) maior o tamanho máximo da string e o gasto em bytes na tabela pra fazer essa referência. Se você escolher usar um text o tamanho máximo da string será o do tipo escolhido (tinytext -> 128, smalltext -> 65536, veja mais aqui) e o tamanho em disco será a referência na tabela (coisa de 2 bytes, por registro) mais o espaço utilizado pela string.

Aí alguém pergunta: “porque não usar sempre text ao invés de varchar?”. Simples. O tipo text não aceita valores default nem pode ser utilizado como chave, a menos que você diga quantos bytes quer pegar do começo da string para usar como chave, respeitando sempre os 760 bytes de limite na chave do índice. Uma curiosidade sobre o text é que a única diferença entre ele e o tipo blob (strings com conteúdo binário, arquivos) é que o blob é case sensitive nas comparações ao contrário do text.

7 Comentários leave one →
  1. 15/10/2009 19:17

    42

    • 15/10/2009 19:56

      E o Mr. Pink?

  2. Gabrielle permalink
    16/10/2009 14:39

    Em um sistema que fiz para uma clínica, um tanto antigo, tenho tal problema.. Eu Calculei uma média de tamanho para nome e cheguei a conclusão que 36 caracteres estava muito bom para o campo de nome do paciente. Óbvio que esse sistema sofre de problemas, não por que 36 caracteres em um nome sejam poucos, mas porque no Edit, acentos e outras coisas acabam sendo contatos como 1 caracter, mas no banco não. Então quando o nome é salvo no banco há perda do Sobrenome do indivíduo. Percebam aqui o nascimento do meu karma. Maldito charset.

    • 17/10/2009 0:10

      HAHAHA. Unicode, minha cara, unicode…

      PS: Só pra constar, meu nome tem 37 caracteres.

    • Danilo permalink
      25/10/2009 10:17

      Uma validação de campo resolveria fácil o problema da perda de um dos nomes.

  3. Lessa permalink
    17/10/2009 10:01

    Esses SGBD’s realmente podem assustar, principalmente se você é um desenvolvedor do tipo aventureiro,assim como eu,que não se incomoda (muito) com o tempo que pode perder até descobrir as particularidades do SGBD.Ainda não tive muitos problemas com o tamanho dos campos, porém já queimei alguns neurônios pra descobrir qual o melhor tipo de campo usar.
    Por exemplo, demorei até descobrir que pra simular um IDENTIFY no Postgree eu tinha que definir o tipo do campo como Serial.

Trackbacks

  1. Twitter Trackbacks for Varchar ou não varchar? Eis a questão « iCaju [icaju.wordpress.com] on Topsy.com

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: