varchar (max) en todas partes?

81

¿Hay algún problema con hacer que todas las columnas de cadenas de Sql Server 2008 sean varchar (max)? Mis tamaños de cadena permitidos son administrados por la aplicación. La base de datos debería persistir lo que le doy. ¿Tendré un impacto en el rendimiento al declarar que todas las columnas de cadenas son de tipo varchar (max) en Sql Server 2008, sin importar el tamaño de los datos que realmente entran en ellas?

BowserKingKoopa
fuente
1
En mi lectura, suena como el tamaño automático de las columnas varchar de Sql Server. Entonces, ¿una columna varchar (max) donde la longitud máxima de cualquier valor dado es 20 no sería la misma que una columna varchar (20)?
BowserKingKoopa

Respuestas:

49

Al usar VARCHAR(MAX), básicamente le está diciendo a SQL Server "almacene los valores en este campo como mejor le parezca", SQL Server elegirá si desea almacenar los valores como un objeto regular VARCHARo como un LOB (objeto grande). En general, si los valores almacenados tienen menos de 8.000 bytes, SQL Server tratará los valores como un VARCHARtipo normal .

Si los valores almacenados son demasiado grandes, entonces se permite que la columna se desborde de la página en páginas LOB, exactamente como lo hacen con otros tipos de LOB ( text, ntexty image); si esto sucede, se requieren lecturas de página adicionales para leer los datos almacenados en las páginas adicionales (es decir, hay un penatly de rendimiento), sin embargo, esto solo ocurre si los valores almacenados son demasiado grandes .

De hecho, en SQL Server 2008 o posterior, los datos pueden desbordarse en páginas adicionales incluso con los tipos de datos de longitud fija (p VARCHAR(3,000). Ej. ); Sin embargo, estas páginas se denominan páginas de datos de desbordamiento de filas y se tratan de manera ligeramente diferente.

Versión corta: desde una perspectiva de almacenamiento, no hay ninguna desventaja de usar VARCHAR(MAX)over VARCHAR(N)para algunos N.

(Tenga en cuenta que esto también se aplica a los otros tipos de campos de longitud variable NVARCHARyVARBINARY )

FYI: no puede crear índices en VARCHAR(MAX)columnas

Justin
fuente
Esto solo puede ser cierto para los campos que aceptan valores NULL. Cada columna varchar (max) o nvarchar (max) no nula requiere 24 bytes de asignación fija adicional. docs.microsoft.com/en-us/sql/t-sql/data-types/…
Liazy
34

Los índices no pueden tener más de 900 bytes de ancho para uno. Así que probablemente nunca puedas crear un índice. Si sus datos tienen menos de 900 bytes, use varchar (900).

Esta es una desventaja: porque da

  • rendimiento de búsqueda realmente malo
  • sin restricciones únicas
gbn
fuente
Pero, ¿qué pasa si la columna varchar (max) no tiene ningún valor superior a 900 bytes? ¿Se indexaría entonces? Estoy confundido porque mucho de lo que estoy leyendo hace que los tipos de columna varchar suenen como si se ajustaran automáticamente a su máximo cuando se ingresan los datos. Esto sería perfecto para lo que quiero, porque es la aplicación la que debería decidir el máximo, no la base de datos.
BowserKingKoopa
3
Recibirá una advertencia cuando cree el índice y un error cuando intente insertar> 900. Pero si sus datos son siempre <900, ¿por qué no usar 900? Sí, aunque se almacenan como cadenas de longitud variable.
gbn
8
No sé si mis datos siempre son <900. Esa es una preocupación de lógica empresarial. Si esa regla cambia, debería cambiarla en la lógica empresarial. No debería tener que cambiar también la base de datos. De todos modos, ese es mi objetivo. Para ver si puedo alejar la preocupación por el tamaño de las cadenas de la base de datos sin un impacto notable en el rendimiento.
BowserKingKoopa
2
¿Con qué frecuencia es útil indexar una columna de texto extenso? ¿Incluso valdría la pena indexar algo como una columna varchar (200)? Después de todo, el índice en sí sería ineficaz. La necesidad de buscar "coincidencias exactas" largas parece poco probable. Y las búsquedas de patrones solo se beneficiarían si se conoce el inicio del patrón.
Desilusionado
9

Simon Sabin escribió una publicación sobre esto hace algún tiempo. No tengo tiempo para tomarlo ahora, pero deberías buscarlo, porque él llega a la conclusión de que no debes usar varchar (max) por defecto.

Editado: Simon tiene algunas publicaciones sobre varchar (max). Los enlaces en los comentarios a continuación muestran esto bastante bien. Creo que el más significativo es http://sqlblogcasts.com/blogs/simons/archive/2009/07/11/String-concatenation-with-max-types-stops-plan-caching.aspx , que habla sobre el efecto de varchar (max) en el almacenamiento en caché del plan. El principio general es tener cuidado. Si no necesita que sea máximo, entonces no use max - si necesita más de 8000 caracteres, entonces seguro ... adelante.

Rob Farley
fuente
El primero. Por OMG Ponies.
Rob Farley
Lamento no haber tenido tiempo de encontrar el enlace real, estaba a punto de entrar en una reunión cuando quise disparar la respuesta.
Rob Farley
1
Y más significativamente, este: sqlblogcasts.com/blogs/simons/archive/2009/07/11/…
Rob Farley
6

Para esta pregunta específicamente algunos puntos que no veo mencionados.

  1. En 2005/2008/2008 R2, si se incluye una columna LOB en un índice, esto bloqueará las reconstrucciones de índices en línea.
  2. En 2012, se levantó la restricción de reconstrucción del índice en línea, pero las columnas LOB no pueden participar en la nueva funcionalidad Agregar columnas NOT NULL como una operación en línea .
  3. Los bloqueos se pueden eliminar durante más tiempo en filas que contienen columnas de este tipo de datos. ( más )

Un par de otras razones se cubren en mi respuesta de por qué no en varchar(8000)todas partes .

  1. Sus consultas pueden terminar solicitando grandes concesiones de memoria no justificadas por el tamaño de los datos.
  2. En la tabla con activadores, puede evitar una optimización donde no se agregan etiquetas de control de versiones.
Martin Smith
fuente
5

Hice una pregunta similar antes. obtuve algunas respuestas interesantes. Echale un vistazo aquí Hubo un sitio en el que un tipo habló sobre el detrimento de usar columnas anchas, sin embargo, si sus datos son limitados en la aplicación, mis pruebas lo refutaron. El hecho de que no pueda crear índices en las columnas significa que no los usaría todo el tiempo (personalmente, no los usaría tanto, pero soy un poco purista en ese sentido). Sin embargo, si sabes que no hay mucho almacenado en ellos, no creo que sean tan malos. Si ordena las columnas de un conjunto de registros con un varchar (max) en él (o cualquier columna ancha que sea char o varchar), entonces podría sufrir penalizaciones en el rendimiento. estos podrían resolverse (si es necesario) por índices, pero no puede poner índices en varchar (max). Si desea preparar sus columnas para el futuro, ¿por qué no ponerlas en algo razonable? por ejemplo, una columna de nombre debe tener 255 caracteres en lugar de un máximo ...

AtaLoss
fuente
2

Hay otra razón para evitar el uso de varchar (max) en todas las columnas. Por la misma razón por la que usamos restricciones de verificación (para evitar llenar tablas con basura causada por software erróneo o entradas de usuario), querríamos protegernos contra cualquier proceso defectuoso que agregue muchos más datos de los previstos. Por ejemplo, si alguien o algo intentara agregar 3000 bytes en un campo Ciudad, sabríamos con certeza que algo anda mal y querríamos detener el proceso en seco para depurarlo lo antes posible. También sabríamos que un nombre de ciudad de 3000 bytes no podría ser válido y estropearía los informes y demás si intentáramos usarlo.

Larry Ness
fuente
1

Idealmente, solo debe permitir lo que necesita. Es decir, si está seguro de que una columna en particular (por ejemplo, una columna de nombre de usuario) nunca tendrá más de 20 caracteres, el uso de VARCHAR (20) frente a VARCHAR (MAX) permite que la base de datos optimice las consultas y las estructuras de datos.

Desde MSDN: http://msdn.microsoft.com/en-us/library/ms176089.aspx

Variable-length, non-Unicode character data. n can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes.

¿Realmente alguna vez se acercará a 2 ^ 31-1 bytes para estas columnas?

leepowers
fuente
3
No creo que sea exacto caracterizar esto como "asignación". La base de datos ciertamente no le reserva 2 ^ 31-1 bytes en ningún lugar.
Scott Stafford
1
"una columna de nombre de usuario [..] nunca va a tener más de 20 caracteres" - Bien, hasta que un día el cliente decide que debe ser más larga. Todos hemos estado allí. :)
Steve Smith