¿Cuál es la diferencia entre los tipos de datos MySQL VARCHAR y TEXT?

19

Después de la versión 5.0.3 (que permitió que VARCHAR tuviera 65.535 bytes y dejó de truncar los espacios finales), ¿hay alguna diferencia importante entre estos dos tipos de datos?

Estaba leyendo la lista de diferencias y las dos únicas notables son:

Para los índices en las columnas BLOB y TEXT, debe especificar una longitud de prefijo de índice. Para CHAR y VARCHAR, una longitud de prefijo es opcional. Consulte la Sección 7.5.1, “Índices de columna”.

y

Las columnas BLOB y TEXT no pueden tener valores POR DEFECTO.

Entonces, debido a estas dos limitaciones en el tipo de datos TEXT, ¿por qué lo usarías sobre varchar (65535)? ¿Hay ramificaciones de rendimiento de uno sobre el otro?

Derek Downey
fuente
1
cuando quieres más de 65535 caracteres en los datos?
BlackICE
Aquí hay un hilo de foro bastante bueno sobre puntos de referencia entre varchar y texto: http://forums.mysql.com/read.php?24,105964,105964
dividido el
Debido a que la lista allí realmente hace un buen trabajo al presentar los detalles explícitos, y porque ya tiene la lista enumerada de diferencias, no estoy seguro de que este sea el tipo de pregunta que necesitamos en DBA. ¿Hay alguna razón por la cual la lista que citó y las razones que dio no son lo suficientemente buenas en este caso? De lo contrario, iré a VtC
jcolebrand
1
Actualicé mi pregunta, pero una razón obvia de la que no estoy seguro es el rendimiento de uno sobre el otro. No estoy seguro si hay otras razones no tan obvias
Derek Downey el
Entonces, ¿es justo que lo que pregunte sean las características de rendimiento de uno sobre el otro?
jcolebrand

Respuestas:

13

dividido vinculado a alguna información que explica el problema básico (hay diferencias de rendimiento), pero no es lo suficientemente simple como para decir que uno siempre es mejor que el otro. (de lo contrario, no habría razón para tener ambos). Además, en MyISM, el tamaño máximo de 64k para VARCHAR no es por campo, es por registro.

Básicamente, hay 4 formas de almacenar cadenas en registros de bases de datos:

  1. longitud fija
  2. Cadenas de estilo C (marcadas con un carácter NULL o similar al final de la cadena)
  3. Cadenas de estilo Pascal (unos pocos bytes para indicar la longitud, luego la cadena)
  4. Punteros (guarde la cadena en otro lugar)

MyISM usa algo similar al # 3 para VARCHAR, y un enfoque híbrido para TEXT donde almacena el comienzo de la cadena en el registro, luego el resto de la cadena en otro lugar. InnoDB es similar para VARCHAR, pero almacena el campo TEXTO completo fuera del registro.

Con 1 y 4, las cosas en el registro siempre tienen la misma longitud, por lo que es más fácil saltar si no necesita la cadena, pero necesita cosas después. Tanto el n. ° 2 como el n. ° 3 no son tan malos para las cadenas cortas ... El n. ° 2 tiene que seguir buscando el marcador, mientras que el n. ° 3 puede saltar ... a medida que las cuerdas se alargan, el n. ° 2 empeora para este uso en particular caso.

Si realmente necesita leer la cadena, # 4 es más lento, ya que tiene que leer el registro, luego lea la cadena que podría estar almacenada en otro lugar del disco, dependiendo de cómo lo maneje esa base de datos. El n. ° 1 siempre es bastante sencillo, y de nuevo te encuentras con problemas similares en los que para el n. ° 2 empeora cuanto más larga es la cadena, mientras que el n. ° 3 es un poco peor que el n. ° 2 para cadenas muy pequeñas, pero mejor a medida que se alarga.

Luego están los requisitos de almacenamiento ... # 1 siempre es una longitud fija, por lo que podría tener hinchazón si la mayoría de las cadenas no tienen la longitud máxima. # 2 tiene 1 byte extra; # 3 normalmente tiene 2 bytes adicionales si la longitud máxima = 255, 4 bytes adicionales si un máximo de 64k. # 4 tiene la longitud del puntero, más las reglas para el # 3 típicamente.

Para las implementaciones específicas dentro de MySQL 5.1, los documentos para MyISM indican :

  • Soporte para un verdadero tipo VARCHAR; una columna VARCHAR comienza con una longitud almacenada en uno o dos bytes.
  • Las tablas con columnas VARCHAR pueden tener una longitud de fila fija o dinámica.
  • La suma de las longitudes de las columnas VARCHAR y CHAR en una tabla puede ser de hasta 64 KB.

Mientras que para InnoDB :

  • La parte de longitud variable del encabezado del registro contiene un vector de bits para indicar columnas NULL. Si el número de columnas en el índice que puede ser NULL es N, el vector de bits ocupa bytes CEILING (N / 8). (Por ejemplo, si hay entre 9 y 15 columnas que pueden ser NULL, el vector de bits usa dos bytes). Las columnas que son NULL no ocupan espacio aparte del bit en este vector. La parte de longitud variable del encabezado también contiene las longitudes de las columnas de longitud variable. Cada longitud toma uno o dos bytes, dependiendo de la longitud máxima de la columna. Si todas las columnas del índice NO SON NULAS y tienen una longitud fija, el encabezado del registro no tiene una parte de longitud variable.
  • Para cada campo de longitud variable no NULL, el encabezado del registro contiene la longitud de la columna en uno o dos bytes. Solo se necesitarán dos bytes si parte de la columna se almacena externamente en páginas de desbordamiento o si la longitud máxima supera los 255 bytes y la longitud real supera los 127 bytes. Para una columna almacenada externamente, la longitud de dos bytes indica la longitud de la parte almacenada internamente más el puntero de 20 bytes a la parte almacenada externamente. La parte interna es de 768 bytes, por lo que la longitud es de 768 + 20. El puntero de 20 bytes almacena la longitud real de la columna.

...

Al igual que con muchas otras cosas cuando se trata de bases de datos, si no está seguro de lo que es mejor para sus necesidades, intente compararlo con datos y uso similares, y vea cómo se comportan.

Joe
fuente
El hilo dividió estados unido que almacena MySQL manchas y campos de texto en línea forums.mysql.com/read.php?24,105964,267596#msg-267596
Michael Mior
1
Nitpick ... Para todos los fines prácticos, no hay límite de 64 KB en una fila en ninguno de los motores. LONGTEXTy LONGBLOBson un ejemplo de ello. MySQL no utiliza cadenas de estilo C (que yo sepa). InnoDB utiliza un enfoque 'híbrido', pero es más complejo, dependiendo del tamaño de la fila, el formato de fila, etc. El almacenamiento de cadenas en una longitud "fija" casi nunca es aconsejable, excepto cuando en realidad tienen una longitud constante (código_país, código postal, etc.) . InnoDB tiene 4 ROW_FORMATs; el texto discute solo 1 o 2 de ellos.
Rick James
2

Cuando un SELECT necesita crear una tabla temporal (como ordenar los resultados), creará una tabla MEMORY o una tabla MyISAM. La memoria es más eficiente. Hay restricciones en MEMORY: una es no permitir TEXT y BLOB. Por lo tanto, un SELECT puede ejecutarse más lentamente con TEXTO que VARCHAR.

Rick James
fuente