¿Hay desventajas al usar un varchar genérico (255) para todos los campos basados en texto?


Tengo a contacts tabla que contiene campos como postcode, first name, last name, town, country, phone number etc, todos los cuales son definidos como VARCHAR(255) aunque ninguno de estos campos se va a venir cerca de 255 caracteres. (Si te estás preguntando, es de esta manera porque Ruby on Rails migra campos de cadena a VARCHAR(255) por defecto y nunca me molesté en sobrescribirlo).

Dado que VARCHAR solo almacenará el número de caracteres reales del campo (junto con la longitud del campo), ¿alguna ventaja distintiva (rendimiento o no) de usar, digamos, VARCHAR(16) sobre VARCHAR(255)?

Además, la mayoría de estos campos tienen índices en ellos. ¿Afecta un tamaño VARCHAR más grande en el campo el tamaño o el rendimiento del índice en absoluto?

Para tu información estoy usando MySQL 5.

 92
Author: Nathan Koop, 2008-11-04

7 answers

En almacenamiento, VARCHAR(255) es lo suficientemente inteligente como para almacenar solo la longitud que necesita en una fila dada, a diferencia de CHAR(255) que siempre almacenaría 255 caracteres.

Pero ya que etiquetó esta pregunta con MySQL, mencionaré un consejo específico de MySQL: como las filas se copian de la capa del motor de almacenamiento a la capa SQL, los campos VARCHAR se convierten a CHAR para obtener la ventaja de trabajar con filas de ancho fijo. Así que las cadenas en la memoria se vuelven acolchadas a la longitud máxima de su declarado VARCHAR columna.

Cuando su consulta genera implícitamente una tabla temporal, por ejemplo, mientras ordena o GROUP BY, esto puede usar mucha memoria. Si utiliza muchos campos VARCHAR(255) para datos que no necesitan ser tan largos, esto puede hacer que la tabla temporal sea muy grande.

También le gustaría saber que este comportamiento de "relleno" significa que una cadena declarada con el conjunto de caracteres utf8 rellena a tres bytes por carácter, incluso para cadenas que almacena con contenido de un solo byte (por ejemplo, caracteres ascii o latin1). Y del mismo modo, el conjunto de caracteres utf8mb4 hace que la cadena se rellene a cuatro bytes por carácter en la memoria.

Así que un VARCHAR(255) en utf8 que almacena una cadena corta como "No opinion" toma 11 bytes en el disco (diez caracteres de charset inferior, más un byte para la longitud) pero toma 765 bytes en memoria, y por lo tanto en tablas temporales o resultados ordenados.

He ayudado a los usuarios de MySQL que sin saberlo crearon tablas temporales de 1.5 GB con frecuencia y llenaron su espacio en disco. Le tenía muchas columnas VARCHAR(255) que en la práctica almacenaban cadenas muy cortas.

Es mejor definir la columna en función del tipo de datos que desea almacenar. Tiene beneficios para hacer cumplir las restricciones relacionadas con la aplicación, como otras personas han mencionado. Pero tiene los beneficios físicos para evitar el desperdicio de memoria que describí anteriormente.

Es difícil saber cuál es la dirección postal más larga, por supuesto, por lo que muchas personas eligen una larga VARCHAR que ciertamente es más larga que cualquier dirección. Y 255 es habitual porque es la longitud máxima de a VARCHAR para la cual la longitud puede codificarse con un byte. También era la longitud máxima VARCHAR en MySQL anterior a 5.0.

 121
Author: Bill Karwin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-07 17:50:03

Además de las consideraciones de tamaño y rendimiento de establecer el tamaño de un varchar (y posiblemente más importante, ya que el almacenamiento y el procesamiento se vuelven más baratos cada segundo), la desventaja de usar varchar(255) "solo porque" se reduce la integridad de los datos.

Definir límites máximos para cadenas es una buena cosa que hacer para evitar que cadenas más largas de lo esperado entren en el RDBMS y causen sobrecargas de búfer o excepciones/errores más tarde al recuperar y analizar valores de la base de datos que son más largos (más bytes) de lo esperado.

Por ejemplo, si tiene un campo que acepta cadenas de dos caracteres para abreviaturas de países, entonces no tiene ninguna razón concebible para esperar que sus usuarios (en este contexto, programadores) ingresen nombres completos de países. Dado que no desea que ingresen "Antigua y Barbuda" (AG) o "Isla Heard y Islas McDonald" (HM), no lo permite en la capa de base de datos. Además, es probable que algunos programadores aún no tengan RTFMed la documentación de diseño ( que seguramente existe) para saber no hacer esto.

Establezca el campo para aceptar dos caracteres y deje que el RDBMS se ocupe de él (bien truncando o mal rechazando su SQL con un error).

Ejemplos de datos reales que no tienen razón para exceder una cierta longitud:

Y así sucesivamente...

Tómese el tiempo para pensar en sus datos y sus límites. Si eres arquitecto, desarrollador o programador, es tu trabajo , después de todo.

Al usar un varchar(n) en lugar de varchar (255) se elimina el problema donde los usuarios (usuarios finales, programadores, otros programas) ingresan inesperadamente datos largos que regresarán para atormentar su código más tarde.

Y no dije que no debería implementar esta restricción en el código de lógica de negocios utilizado por su aplicación.

 24
Author: shufler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-11 19:46:15

Estoy contigo. La atención exigente al detalle es un dolor en el cuello y tiene un valor limitado.

Érase una vez, el disco era un bien preciado y solíamos sudar balas para optimizarlo. El precio del almacenamiento se ha reducido en un factor de 1,000, lo que hace que el tiempo dedicado a exprimir cada byte sea menos valioso.

Si utiliza solo campos CHAR, puede obtener filas de longitud fija. Esto puede ahorrar algo de re-estado real del disco si seleccionó tamaños precisos para los campos. Usted puede ser que consiga más densamente-embalado datos (menos E / S para análisis de tablas) y actualizaciones más rápidas (más fácil de localizar espacios abiertos en un bloque para actualizaciones e inserciones.)

Sin embargo, si sobreestimas tus tamaños, o los tamaños reales de tus datos son variables, terminarás perdiendo espacio con campos de caracteres. Los datos terminarán menos densamente empaquetados (lo que llevará a más E/S para grandes recuperaciones).

Generalmente, los beneficios de rendimiento al intentar poner un tamaño en los campos variables son menores. Usted puede comparar fácilmente mediante el uso de VARCHAR(255) comparado con CHAR(x) para ver si puedes medir la diferencia.

Sin embargo, a veces, necesito proporcionar una pista "pequeña", "mediana", "grande". Así que uso 16, 64 y 255 para los tamaños.

 12
Author: S.Lott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-04 16:27:09

Hoy en día, no puedo imaginar que realmente importe más.

Hay una sobrecarga computacional al usar campos de longitud variable, pero con los excesos de las CPU hoy en día, ni siquiera vale la pena considerarlo. El sistema de E / S es tan lento como para hacer que cualquier costo computacional para manejar varchars sea efectivamente inexistente. De hecho, el precio de un varchar computacionalmente es probablemente una ganancia neta sobre la cantidad de espacio en disco ahorrado mediante el uso de campos de longitud variable sobre campos de longitud fija. Lo más probable es que tengas mayor densidad de hileras.

Ahora, la complejidad de los campos varchar es que no se puede localizar fácilmente un registro a través de su número de registro. Cuando tiene un tamaño de fila de longitud fija (con campos de longitud fija), es trivial calcular el bloque de disco al que apunta un id de fila. Con un tamaño de fila de longitud variable, que tipo de va por la ventana.

Entonces, ahora necesita mantener algún tipo de índice de números de registro, al igual que cualquier otra clave primaria, O necesita hacer un identificador de fila robusto que codifique detalles (como el bloque, etc.) en el identificador. Si lo hace, sin embargo, el id tendría que ser recalculado si alguna vez la fila se mueve en el almacenamiento persistente. No es gran cosa, solo necesita reescribir todas las entradas del índice y asegurarse de que a) nunca lo exponga al consumidor o b) nunca afirme que el número es confiable.

Pero ya que tenemos campos varchar hoy, el único valor de varchar(16) sobre varchar (255) es que la base de datos hará cumplir el límite de 16 caracteres en el varchar(16). Si el modelo DB se supone que es realmente representativo del modelo de datos físicos, entonces tener longitudes de campos puede ser de valor. Si, sin embargo, es simplemente "almacenamiento" en lugar de un "modelo y almacenamiento", no hay necesidad alguna.

Entonces simplemente necesita discernir entre un campo de texto que es indexable (como varchar) vs algo que no lo es (como un campo de texto o CLOB). Los campos indexables tienden a tener un límite de tamaño para facilitar el índice, mientras que los campos CLOB no (dentro de lo razonable).

 12
Author: Will Hartung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-04 16:50:11

En mi experiencia, si permites un tipo de datos de 255 caracteres, algún usuario estúpido (o algún probador experimentado) realmente llenará eso.

Entonces tiene todo tipo de problemas, incluido el espacio que permite para esos campos en los informes y en las pantallas de su aplicación. Sin mencionar la posibilidad de exceder el límite por fila para los datos en su base de datos (si tuviera más de algunos de estos campos de 255 caracteres).

Mucho más fácil elegir un límite razonable en el principio, a continuación, hacer cumplir que a través de la aplicación y la base de datos.

 5
Author: BradC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-04 17:39:17

Es una buena práctica asignar solo un poco más de lo que necesita. Los números de teléfono nunca serían tan grandes.

Una razón es que a menos que valides contra entradas grandes, no hay duda de que alguien usará todo lo que hay. Entonces podrías quedarte sin espacio en tu fila. No estoy seguro sobre el límite de MySQL, pero 8060 es el tamaño máximo de fila en MS SQL.

Un valor predeterminado más normal sería 50 en mi humilde opinión, y luego aumentarlo cuando la necesidad lo demuestre.

 0
Author: dove,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-04 16:07:37

En un contexto mysql puede ser importante cuando se trabaja con índices en dichas columnas varchar, ya que mysql tiene un máx. límite de 767bytes por fila de índice.

Esto significa que al agregar un índice a través de varias columnas varchar 255, puede llegar a este límite bastante rápido / incluso más rápido en columnas utf8 o utf8mb4 como se señaló en las respuestas anteriores

 0
Author: staabm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-15 08:57:07