Tengo una contacts
tabla que contiene campos tales como postcode
, first name
, last name
, town
, country
, phone number
etc, todos los cuales se definen como VARCHAR(255)
a pesar de que ninguno de estos campos nunca se acercará a tener 255 caracteres. (Si se está preguntando, es así porque las migraciones de Ruby on Rails asignan campos de cadena a VARCHAR(255)
de forma predeterminada y nunca me molesté en anularlo).
Dado que VARCHAR solo almacenará el número de caracteres reales del campo (junto con la longitud del campo), ¿hay alguna ventaja distintiva (de rendimiento o de otro tipo) en usar, digamos, VARCHAR(16)
over VARCHAR(255)
?
Además, la mayoría de estos campos tienen índices. ¿Un tamaño de VARCHAR más grande en el campo afecta en absoluto el tamaño o el rendimiento del índice?
Para su información, estoy usando MySQL 5.
Respuestas:
En almacenamiento,
VARCHAR(255)
es lo suficientemente inteligente como para almacenar solo la longitud que necesita en una fila determinada, a diferencia deCHAR(255)
lo que siempre almacenaría 255 caracteres.Pero como etiquetó esta pregunta con MySQL, mencionaré un consejo específico de MySQL: a medida que las filas se copian desde la capa del motor de almacenamiento a la capa SQL, los
VARCHAR
campos se conviertenCHAR
para obtener la ventaja de trabajar con filas de ancho fijo. Entonces, las cadenas en la memoria se rellenan hasta la longitud máxima de suVARCHAR
columna declarada .Cuando su consulta genera implícitamente una tabla temporal, por ejemplo, mientras ordena o
GROUP BY
, esto puede usar mucha memoria. Si usa muchosVARCHAR(255)
campos para datos que no necesitan ser tan largos, esto puede hacer que la tabla temporal sea muy grande.También puede interesarle saber que este comportamiento de "relleno" significa que una cadena declarada con el juego de caracteres utf8 se reduce a tres bytes por carácter, incluso para las cadenas que almacena con contenido de un solo byte (por ejemplo, caracteres ascii o latin1). Y del mismo modo, el juego de caracteres utf8mb4 hace que la cadena se rellene hasta cuatro bytes por carácter en la memoria.
Entonces,
VARCHAR(255)
en utf8 almacenar una cadena corta como "Sin opinión" toma 11 bytes en el disco (diez caracteres de juego de caracteres inferiores, más un byte de longitud) pero toma 765 bytes en memoria y, por lo tanto, en tablas temporales o resultados ordenados.He ayudado a usuarios de MySQL que, sin saberlo, creaban tablas temporales de 1,5 GB con frecuencia y ocupaban su espacio en disco. Tenían muchas
VARCHAR(255)
columnas que en la práctica almacenaban cadenas muy cortas.Es mejor definir la columna según el tipo de datos que desea almacenar. Tiene beneficios para hacer cumplir las restricciones relacionadas con la aplicación, como han mencionado otras personas. 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 dirección larga
VARCHAR
que ciertamente es más larga que cualquier dirección. Y 255 es habitual porque es la longitud máxima de aVARCHAR
para la que la longitud se puede codificar con un byte. También fue laVARCHAR
longitud máxima en MySQL anterior a 5.0.fuente
255
se usaba para que la longitud de la cadena pudiera caber en un solo byteAdemá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 abaratan cada segundo), la desventaja de usar varchar (255) "solo porque" es la integridad de los datos reducida .
Definir límites máximos para cadenas es algo bueno para evitar que cadenas más largas de lo esperado ingresen al RDBMS y causen desbordes de búfer o excepciones / errores más adelante 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, no tiene ninguna razón concebible para esperar que sus usuarios (en este contexto, programadores) ingresen nombres completos de países. Como no desea que ingresen "Antigua y Barbuda" (AG) o "Islas Heard y McDonald" (HM), no lo permite en la capa de la base de datos. Además, es probable que algunos programadores aún no hayan RTFMed la documentación de diseño ( que seguramente existe ) para saber que no deben hacer esto.
Configure el campo para que acepte dos caracteres y deje que el RDBMS lo maneje (ya sea con gracia truncando o sin gracia al rechazar su SQL con un error).
Ejemplos de datos reales que no tienen por qué superar una determinada longitud:
Y así...
Tómese el tiempo para pensar en sus datos y sus límites. Si eres arquitecto, desarrollador o programador , después de todo , es tu trabajo .
Al usar varchar (n) en lugar de varchar (255), elimina el problema donde los usuarios (usuarios finales, programadores, otros programas) ingresan datos inesperadamente largos que volverán a atormentar su código más adelante.
Y no dije que no debas implementar también esta restricción en el código de lógica empresarial que usa tu aplicación.
fuente
the design documentation (which surely exists)
Ja. : DEstoy contigo. La atención exigente a los detalles es un dolor de cabeza y tiene un valor limitado.
Érase una vez, el disco era un bien preciado y solíamos sudar mucho 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 usa solo campos CHAR, puede obtener filas de longitud fija. Esto puede ahorrar algunos cambios en el estado real del disco si seleccionó tamaños precisos para los campos. Es posible que obtenga datos más densamente empaquetados (menos E / S para escaneos de tablas) y actualizaciones más rápidas (más fácil de ubicar espacios abiertos en un bloque para actualizaciones e inserciones).
Sin embargo, si sobreestima sus tamaños, o si los tamaños reales de sus datos son variables, terminará desperdiciando espacio con los campos CHAR. Los datos terminarán empaquetados menos densamente (lo que generará más E / S para grandes recuperaciones).
Generalmente, los beneficios de rendimiento de intentar asignar un tamaño a los campos variables son menores. Puede comparar fácilmente utilizando VARCHAR (255) en comparación con CHAR (x) para ver si puede medir la diferencia.
Sin embargo, a veces, necesito proporcionar una pista "pequeña", "mediana", "grande". Entonces uso 16, 64 y 255 para los tamaños.
fuente
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 CPU en la actualidad, ni siquiera vale la pena considerarlo. El sistema de E / S es tan lento que hace que los costos computacionales para manejar varchars sean efectivamente inexistentes. De hecho, el precio de un varchar computacionalmente es probablemente una ganancia neta sobre la cantidad de espacio en disco que se ahorra al usar campos de longitud variable sobre campos de longitud fija. Lo más probable es que tenga una mayor densidad de filas.
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 una identificación de fila. Con un tamaño de fila de longitud variable, eso se pierde por la ventana.
Entonces, ahora necesita mantener algún tipo de índice de número de registro, como cualquier otra clave primaria, O necesita hacer un identificador de fila robusto que codifique detalles (como el bloque, etc.) en el identificador. Sin embargo, si hace eso, la identificación tendrá que volver a calcularse si alguna vez la fila se mueve al almacenamiento persistente. No es gran cosa, solo necesita reescribir todas las entradas del índice y asegurarse de que a) nunca lo exponga al consumidor ob) nunca afirme que el número es confiable.
Pero dado que tenemos campos varchar hoy, el único valor de varchar (16) sobre varchar (255) es que la base de datos aplicará el límite de 16 caracteres en varchar (16). Si se supone que el modelo de base de datos es realmente representativo del modelo de datos físicos, entonces puede ser valioso tener campos de longitud. Sin embargo, si es simplemente "almacenamiento" en lugar de un "modelo Y almacenamiento", no hay ninguna necesidad.
Luego, simplemente necesita discernir entre un campo de texto que es indexable (como varchar) y 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 lo tienen (dentro de lo razonable).
fuente
En mi experiencia, si permite un tipo de datos de 255 caracteres, algún usuario estúpido (o algún probador experimentado) realmente lo completará.
Luego, tiene todo tipo de problemas, incluido el espacio que permite para esos campos en los informes y las visualizaciones en pantalla de su aplicación. Sin mencionar la posibilidad de exceder el límite por fila de datos en su base de datos (si tuviera más de algunos de estos campos de 255 caracteres).
Es mucho más fácil elegir un límite razonable al principio y luego aplicarlo a través de la aplicación y la base de datos.
fuente
Es una buena práctica asignar solo un poco más de lo que necesita. Los números de teléfono nunca llegarían a ser tan grandes.
Una razón es que, a menos que valide contra entradas grandes, sin duda alguien usará todo lo que haya. Entonces puede que te quedes sin espacio en tu fila. No estoy seguro del límite de MySQL, pero 8060 es el tamaño máximo de filas en MS SQL.
Un valor predeterminado más normal sería 50 en mi humilde opinión, y luego aumentar donde la necesidad lo demuestre.
fuente
En un contexto de mysql, puede ser importante cuando se trabaja con índices en dichas columnas varchar, ya que mysql tiene un max. límite de 767 bytes por fila de índice.
Esto significa que al agregar un índice en varias columnas varchar 255, puede llegar a este límite bastante rápido / incluso más rápido en las columnas utf8 o utf8mb4 como se señaló en las respuestas anteriores
fuente