Qual é a diferença entre os tipos de dados MySQL VARCHAR e TEXT?

19

Após a versão 5.0.3 (que permitia que o VARCHAR tivesse 65.535 bytes e parou de truncar espaços à direita), existe alguma diferença importante entre esses dois tipos de dados?

Eu estava lendo a lista de diferenças e as duas únicas são:

Para índices nas colunas BLOB e TEXT, você deve especificar um comprimento de prefixo de índice. Para CHAR e VARCHAR, um comprimento de prefixo é opcional. Consulte a Seção 7.5.1, “Índices de colunas”.

e

As colunas BLOB e TEXT não podem ter valores PADRÃO.

Portanto, devido a essas duas limitações no tipo de dados TEXT, por que você o utilizaria sobre o varchar (65535)? Existem ramificações de desempenho de uma sobre a outra?

Derek Downey
fonte
1
quando você deseja mais de 65535 caracteres nos dados?
BlackICE
Aqui está um tópico muito bom no fórum sobre benchmarks entre varchar e texto: http://forums.mysql.com/read.php?24,105964,105964
dividido em
Como a lista lá realmente faz um bom trabalho de organizar os detalhes explícitos e como você já possui a lista enumerada de diferenças, não tenho certeza se esse é o tipo de pergunta que precisamos no DBA. Existe uma razão para a lista que você citou e as razões que você deu não serem boas o suficiente nesse caso? Caso contrário, eu vou VTC
jcolebrand
1
Atualizei minha pergunta, mas um motivo óbvio pelo qual não tenho certeza é o desempenho de um sobre o outro. Não tenho certeza se há outras razões não tão óbvias
Derek Downey
Então, é justo que você esteja perguntando quais são as características de desempenho de um sobre o outro?
jcolebrand

Respostas:

13

dividido vinculado a algumas informações que explicam o problema básico (há diferenças de desempenho), mas não é simples o suficiente para dizer que um é sempre melhor que o outro. (caso contrário, não haveria razão para ter os dois.) Além disso, no MyISM, o tamanho máximo de 64k do VARCHAR não é por campo - é por registro.

Basicamente, existem 4 maneiras de armazenar seqüências de caracteres nos registros do banco de dados:

  1. comprimento fixo
  2. Seqüências de caracteres no estilo C (marcadas com um caractere NULL ou semelhante no final da sequência)
  3. Sequências de caracteres em estilo Pascal (alguns bytes para indicar o comprimento, depois a sequência)
  4. Ponteiros (armazene a string em outro lugar)

O MyISM usa algo semelhante ao nº 3 para o VARCHAR e uma abordagem híbrida para o TEXT, onde ele armazena o início da string no registro e o restante da string em outro lugar. O InnoDB é semelhante ao VARCHAR, mas armazena o campo TEXTO completo fora do registro.

Com 1 e 4, as coisas no registro são sempre do mesmo tamanho, por isso é mais fácil pular se você não precisar da string, mas precisar dela depois. Tanto o segundo como o terceiro não são tão ruins para as cordas curtas ... o nº 2 deve continuar procurando o marcador, enquanto o nº 3 pode pular adiante ... à medida que as cordas ficam mais longas, o nº 2 fica pior para esse uso específico caso.

Se você realmente precisa ler a sequência, o número 4 é mais lento, pois você precisa ler o registro e, em seguida, leia a sequência que pode ser armazenada em outro local do disco, dependendo de como o banco de dados lida com isso. O número 1 é sempre bem direto e, novamente, você se depara com problemas semelhantes, onde o número 2 piora quanto mais tempo a corda é, enquanto o número 3 é um pouco pior que o número 2 para cordas muito pequenas, mas melhor à medida que aumenta.

Depois, há requisitos de armazenamento ... O número 1 é sempre um comprimento fixo, portanto pode haver inchaço se a maioria das cordas não tiver o tamanho máximo. # 2 tem 1 byte extra; O nº 3 normalmente possui 2 bytes extras se o comprimento máximo = 255, 4 bytes extras se o tamanho máximo for 64k. O item 4 tem o comprimento do ponteiro, mais as regras do item 3 normalmente.

Para implementações específicas no MySQL 5.1, o documentos para o MyISM afirmam :

  • Suporte para um verdadeiro tipo VARCHAR; uma coluna VARCHAR começa com um comprimento armazenado em um ou dois bytes.
  • As tabelas com colunas VARCHAR podem ter comprimento de linha fixo ou dinâmico.
  • A soma dos comprimentos das colunas VARCHAR e CHAR em uma tabela pode ser de até 64 KB.

Enquanto para o InnoDB :

  • A parte de comprimento variável do cabeçalho do registro contém um vetor de bits para indicar colunas NULL. Se o número de colunas no índice que pode ser NULL for N, o vetor de bit ocupará CEILING (N / 8) bytes. (Por exemplo, se houver entre 9 e 15 colunas que podem ser NULL, o vetor de bit usa dois bytes.) As colunas NULL não ocupam espaço além do bit desse vetor. A parte de comprimento variável do cabeçalho também contém os comprimentos das colunas de comprimento variável. Cada comprimento ocupa um ou dois bytes, dependendo do comprimento máximo da coluna. Se todas as colunas no índice NÃO forem nulas e tiverem um comprimento fixo, o cabeçalho do registro não terá parte de comprimento variável.
  • Para cada campo de comprimento variável diferente de NULL, o cabeçalho do registro contém o comprimento da coluna em um ou dois bytes. Só serão necessários dois bytes se parte da coluna estiver armazenada externamente em páginas excedentes ou se o comprimento máximo exceder 255 bytes e o comprimento real exceder 127 bytes. Para uma coluna armazenada externamente, o comprimento de dois bytes indica o comprimento da parte armazenada internamente mais o ponteiro de 20 bytes para a parte armazenada externamente. A parte interna tem 768 bytes, portanto, o comprimento é 768 + 20. O ponteiro de 20 bytes armazena o comprimento real da coluna.

...

como em muitas outras coisas ao lidar com bancos de dados, se você não tem certeza do que é melhor para suas necessidades, tente compará-lo com dados e uso semelhantes e veja como eles se comportam.

Joe
fonte
O fio dividido estados ligados que o MySQL armazena blobs e campos de texto em linha forums.mysql.com/read.php?24,105964,267596#msg-267596
Michael Mior
1
Nitpick ... Para todos os fins práticos, não há limite de 64 KB em uma linha nos dois Mecanismos. LONGTEXTe LONGBLOBsão um exemplo disso. Strings de estilo C não são usadas em lugar algum pelo MySQL (que eu saiba). O InnoDB usa uma abordagem 'híbrida', mas é mais complexa, dependendo do tamanho da linha, formato da linha, etc. O armazenamento de seqüências de caracteres no tamanho "fixo" quase nunca é aconselhável, exceto quando na verdade elas são de comprimento constante (código_de_ país, código_de_ código, etc) . O InnoDB possui 4 ROW_FORMATs; o texto discute apenas 1 ou 2 deles.
Rick James
2

Quando um SELECT precisa criar uma tabela temporária (por exemplo, para classificar os resultados), ele cria uma tabela MEMORY ou uma tabela MyISAM. MEMORY é mais eficiente. Existem restrições à MEMÓRIA - uma é proibir o TEXT e o BLOB. Portanto, um SELECT pode executar mais devagar com TEXT que VARCHAR.

Rick James
fonte