¿Por qué no usar varchar (max)?

76

Soy un poco anticuado en lo que respecta al diseño de bases de datos, así que estoy totalmente a favor de usar los tamaños de datos correctos en las columnas. Sin embargo, al revisar la base de datos de un amigo, noté que usaba varchar(max)mucho. Ahora, mi pensamiento inmediato fue devolvérselo y decirle que lo cambiara. Pero luego lo pensé y no pude encontrar una buena razón para que no lo usara (había usado una herramienta de tipo de caso para generar la base de datos, si se lo está preguntando).

He estado investigando el tema del varchar(max)uso y realmente no puedo encontrar una buena razón para que no lo use.

No usa las columnas para los índices, la aplicación que se encuentra en la base de datos tiene limitaciones en la entrada, por lo que no permitirá entradas masivas en los campos.

Se agradecería cualquier ayuda que me ayude a hacerle ver la luz :).

AtaLoss
fuente
1
Vea esta respuesta por otro motivo stackoverflow.com/questions/2009694/…
Martin Smith
¡Eso es interesante! lástima que no encontré esto antes. ¡Gracias!
AtaLoss
5
Por un lado: no se puede poner un índice en una VARCHAR(MAX)columna ... eso solo me hace usarlo solo cuando es absolutamente necesario ...
marc_s
1
Señalaré que esperar que la aplicación controle siempre la entrada es una estupidez. Los datos casi siempre durarán más que la aplicación y es posible que la próxima versión de la aplicación no tenga los límites correctos.
HLGEM

Respuestas:

35

Mi respuesta a esto no se trata del uso de Max, sino del motivo de VARCHAR (max) vs TEXT.

En mi libro; En primer lugar, a menos que pueda estar absolutamente seguro de que nunca codificará nada más que texto en inglés y la gente no hará referencia a nombres de ubicaciones extranjeras, entonces debe usar NVARCHAR o NTEXT.

En segundo lugar, es lo que los campos le permiten hacer.

TEXT es difícil de actualizar en comparación con VARCHAR, pero obtienes la ventaja de la indexación de texto completo y muchas cosas inteligentes.

Por otro lado, VARCHAR (MAX) tiene cierta ambigüedad, si el tamaño de la celda es <8000 caracteres, se tratará como datos de fila. Si es mayor, se tratará como un LOB a efectos de almacenamiento. Debido a que no puede saber esto sin consultar RBAR, esto puede tener estrategias de optimización para lugares donde necesita estar seguro sobre sus datos y cuántas lecturas cuestan.

De lo contrario, si su uso es relativamente mundano y no espera tener problemas con el tamaño de los datos (es decir, está usando .Net y, por lo tanto, no tiene que preocuparse por el tamaño de sus objetos string / char *) entonces usar VARCHAR (max) está bien.

Russ Clarke
fuente
4
Una cosa que noté en mi lectura de artículos al respecto fue que cuando consulta una tabla, tiene que almacenar el tamaño máximo de un registro en la memoria. por lo que potencialmente podría ser un problema, pero en los entornos actuales con múltiples gigas (si no terabytes) y con RAM siendo barato y fácil de actualizar, prácticamente reduce este problema a nada.
AtaLoss
14
Esta respuesta parece implicar que la indexación de texto completo solo se puede usar con el texttipo de datos. Este no es el caso. textes un tipo de datos obsoleto y no tiene ninguna ventaja sobre varchar(max)AFAIK.
Martin Smith
7
Otra razón para no usar TEXT / NTEXT es que están obsoletos.
Aaron Bertrand
1
¿Puedes citar eso? Solo sabía que TEXT IN ROW estaba en desuso.
Russ Clarke
1
Libros en pantalla de
tibx
12

Hay una publicación de blog sobre por qué no usar varchar max aquí

Editar

La diferencia básica es dónde se almacenan los datos. Una fila de datos SQL tiene un tamaño máximo de 8000 bytes (o eran 8K). Entonces, no se puede almacenar un varchar de 2GB (máx.) En la fila de datos. SQL Server lo almacena "Fuera de fila".

Por lo tanto, podría obtener un impacto en el rendimiento ya que los datos no estarán en el mismo lugar en el disco, consulte: http://msdn.microsoft.com/en-us/library/ms189087.aspx

Shiraz Bhaiji
fuente
1
Sí, lo leí, pero aún me dejó con preguntas. Si el código está codificado correctamente, de modo que los datos estén limitados en la aplicación, entonces no debería tener ninguna degradación del rendimiento. La indexación no era un problema, y ​​el último punto era sobre el diseño, que a mi amigo no le preocupaba.
AtaLoss
1
el varchar (max) no se almacenará fuera de la fila a menos que los datos almacenados en la fila excedan las limitaciones de las filas (que, sí, son aproximadamente 8k). Es decir, si tiene el texto "hola mundo" almacenado en un varchar max en una tabla con 3 columnas, es probable que no se almacene fuera de la fila.
AtaLoss
La razón para no usarlos es que no se pueden indexar. Es una mala práctica usar nvarchar (max) o varchar (max) a menos que espere tener datos que lo necesiten.
HLGEM
No siempre es un éxito de rendimiento. Los escaneos de tablas se acelerarán si el tamaño de la fila disminuye. Si el varchar (max) en cuestión se usa raramente en consultas, moverlo fuera de la fila será una ganancia de rendimiento.
johnnycrash
2
El impacto en el rendimiento vale la corrección operativa cuando no puede anticipar el tamaño de una cadena que podría necesitar insertar en una fila.
binki
2

Si está trabajando en un entorno OLTP, lo más importante es el rendimiento. Desde problemas generales y de ajuste hasta limitaciones de indexación y cuellos de botella en las consultas. El uso de varcahr (max) o cualquier otro tipo de LOB probablemente contravenga la mayoría de las mejores prácticas de diseño, por lo que, a menos que exista una necesidad comercial específica que no pueda manejarse mediante el uso de algún otro mecanismo de escritura y solo un varchar (max) se ajustará al Bill, entonces, ¿por qué someter su sistema y sus aplicaciones al tipo de problemas generales y de rendimiento inherentes a uno de los tipos de datos LOB?

Si, por otro lado, está trabajando en un entorno OLAP o en un entorno Star Schema DW con tablas de dimensiones con campos de descriptores que naturalmente deben ser detallados, entonces un varchar (max), siempre que no lo agregue a un índice, puede ser útil. Aún así, recomendaría usar un char (x) varchar (x), ya que siempre es una buena práctica usar solo aquellos recursos que absolutamente debes tener para hacer el trabajo.

Scott Johnston
fuente
1

NO deben usarse a menos que espere grandes cantidades de datos y esta es la razón (directamente de Libros en línea):

Las columnas que son de los tipos de datos de objeto grande (LOB) ntext, text, varchar (max), nvarchar (max), varbinary (max), xml o image no se pueden especificar como columnas clave para un índice.

Si desea paralizar el rendimiento, use nvarchar para todo.

HLGEM
fuente
2
Pero, ¿qué pasa si nunca va a escribir esa columna en primer lugar? Si está almacenando una mancha de texto, probablemente lo esté buscando en una columna de clave diferente. ¿Cuál es esta gran preocupación de tener que colocar índices en columnas que probablemente almacenarán texto de forma libre y nunca aparecerán WHEREexcepto tal vez para verificar IS NULL?
binki
@binki, el consejo es no usar varchar (max) para todo porque habrá campos que necesitará indexar. Solo está diseñado para cuando necesita grandes cantidades de datos.
HLGEM
1
El hecho de que sea de un libro en línea no significa que sea correcto :) Otro ejemplo del uso a veces correcto de (MAX) es cuando está almacenando cadenas de una fuente (por ejemplo, blobs, campos NOSQL) que no tiene tamaño, por lo que no No sé qué tan grande puede ser. Y estoy de acuerdo con @binki, a menudo hay columnas que sabes que nunca indexarás.
840
1

Redgate escribió un gran artículo sobre esto.
https://www.red-gate.com/simple-talk/sql/database-administration/whats-the-point-of-using-varcharn-anymore/

Conclusiones

  • Cuando sea apropiado, use VARCHAR (n) sobre VARCHAR (MAX) por razones de buen diseño, si no beneficios de rendimiento, y porque los datos VARCHAR (MAX) no se comprimen
  • Almacenar cadenas grandes lleva más tiempo que almacenar cadenas pequeñas.
  • Actualizar un valor VARCHAR (MAX) en fila de menos de 8,000 a más de 8,000 será relativamente lento, pero la diferencia para una sola transacción probablemente no sea medible.
  • Actualizar un valor VARCHAR (MAX) en fila de más de 8.000 a menos de 8.000 será más rápido que si la tabla está configurada para almacenar datos fuera de fila.
  • El uso de la opción fuera de fila para VARCHAR (MAX) provocará escrituras más lentas hasta que las cadenas sean muy largas.
Donny V.
fuente
0

No sé cómo el servidor SQL maneja campos varchar grandes (declarados) desde una perspectiva de rendimiento, memoria y almacenamiento ... pero asumiendo que lo hace tan eficientemente como campos varchar declarados más pequeños, todavía existe el beneficio de las restricciones de integridad.

Se supone que la aplicación que se encuentra en la base de datos tiene límites en la entrada, pero la base de datos puede informar correctamente un error si la aplicación tiene un error a este respecto.

a.
fuente
Este es un buen punto, especialmente si no está utilizando un lenguaje administrado para leer sus cadenas.
Russ Clarke
Es un buen punto. Mencionaré esto, se está desarrollando en c # 3.5 o 4 (creo que debería preguntarle).
AtaLoss
@RussClarke ¿Son las cadenas de longitud variable realmente una cosa solo administrada? Parece que nunca se ha encontrado con la asignación de montón en entornos no administrados :-p.
binki
@MartinSmith Esas son mejoras de rendimiento muy pequeñas. Además, el blogger está usando VARCHAR(MAX)con comparaciones y en la WHEREcláusula. El caso de uso que esperaría VARCHAR(MAX)es algo que no compararía ni WHEREen SQL, por ejemplo, un blob de contenido de publicación de blog, una descripción de texto de forma libre de algo. Si desea comparar o WHERE, por supuesto, la restricción le ayudará. Su ejemplo de 'abc'podría incluso traducirse en una comparación de dos números enteros. Ese no es el tipo de datos que uno pone en un VARCHAR(MAX)
binki
0

La diferencia está en siguiente:
VARCHAR(X)se puede indexar y almacenar en el MDF/NDFarchivo de datos.
VARCHAR(MAX)no se puede indexar porque puede alcanzar un gran volumen y luego se almacenará como un archivo separado y no en el MDF/NDFarchivo de datos.

Vlad Kirov
fuente
6
¿Dónde crees exactamente que MS SQL almacena los datos LOB, si no es en los archivos .mdf?
0

   Es algo anticuado creer que la aplicación solo pasará cadenas cortas a la base de datos, y eso hará que esté bien .

   En los tiempos modernos, TIENES que anticipar que la aplicación actual accederá principalmente a la base de datos, pero puede haber una versión futura de la aplicación (¿sabrá el desarrollador de esa versión mantener las cadenas por debajo de una cierta longitud?)

   usted DEBE anticipar que los servicios web, los procesos ETL, LYNC a SQL, y cualquier otro número de tecnologías, y / o no-todavía-existentes ya existentes serán utilizados para acceder a su base de datos.

   En términos generales, trato de no pasar de varchar (4000), porque después de todo son cuatro mil caracteres . Si excedo eso, busco otros tipos de datos para almacenar lo que sea que esté tratando de almacenar. Brent Ozar ha escrito cosas geniales sobre esto.

   Dicho todo esto, es importante evaluar el enfoque del diseño actual para sus requisitos actuales cuando está trabajando en un proyecto. Tenga una idea de cómo funcionan las distintas partes, comprenda las ventajas y desventajas de los distintos enfoques y resuelva el problema en cuestión. El ejercicio de un gran axioma puede conducir a una adherencia ciega que podría convertirlo en un lemming .

Stephen Lauzon
fuente