¿Hay alguna ventaja de varchar (500) sobre varchar (8000)?

90

He leído sobre esto en los foros de MSDN y aquí y todavía no lo tengo claro. Creo que esto es correcto: Varchar (max) se almacenará como un tipo de datos de texto, por lo que tiene inconvenientes. Entonces, digamos que su campo tendrá menos de 8000 caracteres. Como un campo BusinessName en mi tabla de base de datos. En realidad, el nombre de una empresa probablemente siempre tendrá menos de (sacando un número de mi sombrero) 500 caracteres. Parece que muchos campos varchar con los que me encuentro caen muy por debajo del recuento de caracteres de 8k.

Entonces, ¿debería hacer que ese campo sea varchar (500) en lugar de varchar (8000)? Por lo que entiendo de SQL, no hay diferencia entre esos dos. Entonces, para hacer la vida más fácil, me gustaría definir todos mis campos varchar como varchar (8000). ¿Tiene eso algún inconveniente?

Relacionado: Tamaño de las columnas varchar (no sentí que esta respondiera mi pregunta).

jcollum
fuente
6
Imagínese tratando de incluir un nombre comercial de 500 caracteres en una tarjeta de presentación ... :)
OMG Ponies
2
@OMG Ponies: cada vez que veo tu nombre de usuario me río. Ahora, que estabas diciendo? (Es broma)
jcollum
4
@jcollum: SpaceMan Spiff siempre obtendrá mi voto. Eso no es cierto, cualquier Calvin & Hobbes servirá, pero especialmente los que esculpen la nieve. O el tyranosaurus volando un F-14. Pero estoy divagando ...
OMG Ponies

Respuestas:

20

Desde el punto de vista del procesamiento, no hará ninguna diferencia usar varchar (8000) vs varchar (500). Es más un tipo de "buena práctica" definir una longitud máxima que debe contener un campo y hacer que su varchar tenga esa longitud. Es algo que se puede utilizar para ayudar con la validación de datos. Por ejemplo, hacer que la abreviatura de un estado tenga 2 caracteres o un código postal de 5 o 9 caracteres. Esta solía ser una distinción más importante para cuando sus datos interactuaban con otros sistemas o interfaces de usuario donde la longitud del campo era crítica (por ejemplo, un conjunto de datos de archivos planos de mainframe), pero hoy en día creo que es más un hábito que cualquier otra cosa.

BBlake
fuente
3
Tiene sentido ... para cosas que naturalmente tienen una longitud máxima. Pero, ¿qué haces cuando la longitud máxima no es obvia? Por ejemplo, un nombre comercial.
jcollum
2
Para algo así, si no preveo ninguna forma de pronosticar cuál podría ser el tamaño potencial, generalmente iré con un varchar (8000) o varchar (max), según el tipo de datos
BBlake
4
Parece que esto marca una diferencia en el rendimiento, incluso en 2017: dba.stackexchange.com/a/162117/1822
a_horse_with_no_name
1
Respuestas más recientes muestran que no son costos: afecta a la lógica de optimización de la respuesta de Martin Smith y también tienen en cuenta cuestiones de tamaño 8K fila Total mencionados por GBN y Oliver .
ToolmakerSteve
124

Un ejemplo en el que esto puede marcar la diferencia es que puede evitar una optimización del rendimiento que evita agregar información de versiones de filas a las tablas con desencadenadores posteriores.

Esto está cubierto por SQL Kiwi aquí

El tamaño real de los datos almacenados es irrelevante: lo que importa es el tamaño potencial.

De manera similar, si se usan tablas optimizadas para memoria desde 2016, ha sido posible usar columnas LOB o combinaciones de anchos de columna que potencialmente podrían exceder el límite de entrada pero con una penalización.

Las columnas (máx.) Siempre se almacenan fuera de la fila. Para otras columnas, si el tamaño de la fila de datos en la definición de la tabla puede exceder los 8.060 bytes, SQL Server empuja las columnas de longitud variable más grandes fuera de la fila. Nuevamente, no depende de la cantidad de datos que almacene allí.

Esto puede tener un gran efecto negativo en el consumo y el rendimiento de la memoria

Otro caso en el que la declaración excesiva de los anchos de columna puede suponer una gran diferencia es si la tabla se procesará alguna vez mediante SSIS. La memoria asignada para columnas de longitud variable (no BLOB) es fija para cada fila en un árbol de ejecución y es según la longitud máxima declarada de las columnas, lo que puede conducir a un uso ineficiente de búferes de memoria (ejemplo) . Si bien el desarrollador del paquete SSIS puede declarar un tamaño de columna más pequeño que la fuente, este análisis se realiza mejor desde el principio y se aplica allí.

De vuelta en el motor de SQL Server, un caso similar es que al calcular la concesión de memoria para asignar a las SORToperaciones, SQL Server asume quevarchar(x) columnas consumirán en promediox/2 bytes .

Si la mayoría de sus varcharcolumnas están más llenas, esto puede llevar a que las sortoperaciones se desbordentempdb .

En su caso, si sus varcharcolumnas se declaran como8000 bytes pero en realidad tienen un contenido mucho menor que ese, a su consulta se le asignará memoria que no requiere, lo que obviamente es ineficiente y puede conducir a esperas por concesiones de memoria.

Esto se trata en la Parte 2 del Webcast 1 de talleres de SQL que se puede descargar desde aquí o ver más abajo.

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

Captura de pantalla

SELECT id,name8000
FROM T
ORDER BY number

Captura de pantalla

Martin Smith
fuente
1
entonces, si casi todos mis valores son de 3 o 4 caracteres, no pueden exceder los 4 caracteres nunca, y quiero evitar que "operaciones de clasificación se derramen en tempdb", declararé mi columna VARCHAR (8) y usaré una restricción CHECK para hacer cumplir esa columna el ancho no puede exceder los 4 caracteres. ¿Qué piensas?
AK
12
@AlexKuznetsov - Para esa situación, los declararía ya char(4)que de todos modos hay 2 bytes de sobrecarga por columna variable.
Martin Smith
9

Aparte de las mejores prácticas (respuesta de BBlake)

  • Recibe advertencias sobre el tamaño máximo de fila (8060) bytes y el ancho del índice (900 bytes) con DDL
  • DML morirá si excede estos límites
  • ANSI PADDING ON es el valor predeterminado, por lo que podría terminar almacenando una gran cantidad de espacios en blanco
gbn
fuente
38
Solo para aclarar sobre ANSI PADDING ON: cuando se usan tipos nvarchary varchar, esto solo significa que los espacios finales se conservan al insertarlos, no que los valores se completen con espacios al tamaño de la columna, como en chary nchar.
Ben M
9

Hay algunas desventajas de las columnas grandes que son un poco menos obvias y pueden atraparte un poco más tarde:

  • Todas las columnas que usa en un ÍNDICE no deben exceder los 900 bytes
  • Todas las columnas de una cláusula ORDER BY no pueden superar los 8060 bytes. Esto es un poco difícil de entender ya que solo se aplica a algunas columnas. Consulte el límite de tamaño de fila de SQL 2008 R2 excedido para obtener más detalles)
  • Si el tamaño total de la fila supera los 8060 bytes, aparece un " derrame de página " para esa fila. Esto podría afectar el rendimiento (una página es una unidad de asignación en SQLServer y está fijada en 8000 bytes + algo de sobrecarga. Superar esto no será grave, pero es notorio y debe tratar de evitarlo si puede fácilmente)
  • Muchas otras estructuras de datos internas, búferes y, por último, sus propias variables y variables de tabla, todas necesitan reflejar estos tamaños. Con tamaños excesivos, la asignación de memoria excesiva puede afectar el rendimiento

Como regla general, trate de ser conservador con el ancho de la columna. Si se convierte en un problema, puede expandirlo fácilmente para que se ajuste a sus necesidades. Si observa problemas de memoria más adelante, reducir una columna ancha más adelante puede volverse imposible sin perder datos y no sabrá por dónde empezar.

En su ejemplo de los nombres comerciales, piense en dónde puede mostrarlos. ¿Hay realmente espacio para 500 caracteres? Si no es así, no tiene mucho sentido almacenarlos como tales. http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States enumera algunos nombres de empresas y el máximo es de unos 50 caracteres. Entonces usaría 100 para el máximo de columna. Quizás más como 80.

Oliver
fuente
2

Idealmente, querrá ir más pequeño que eso, hasta una longitud de tamaño razonable (500 no es de tamaño razonable) y asegurarse de que la validación del cliente detecte cuándo los datos serán demasiado grandes y enviarán un error útil.

Si bien el varchar en realidad no va a reservar espacio en la base de datos para el espacio no utilizado, recuerdo que las versiones de SQL Server tienen un rastro de que las filas de la base de datos son más anchas que una cierta cantidad de bytes (no recuerdo el recuento exacto) y en realidad arrojan los datos que no encajaban. Un cierto número de esos bytes se reservó para cosas internas de SQL Server.

Otis
fuente
Es cierto que esto también solía ser una preocupación mucho mayor. Pero hoy en día, el espacio es realmente barato, por lo que no creo que sea una preocupación tan grande, al menos desde mi punto de vista.
BBlake
1
@jcollum: En su ejemplo, 500 no parece tener un tamaño razonable para el nombre de una empresa.
Otis
1
@BBlake: Independientemente del costo de almacenamiento, si SQL Server todavía tiene restricciones de tamaño de fila, no importa cuánto almacenamiento tenga. Puede almacenar todo en bloques de texto, pero hay algunas operaciones SQL que no puede hacer en un blob que puede hacer en un varchar.
Otis
2
@Otis: mi punto es este: no hay una restricción real sobre el tamaño de un nombre comercial. A menos que haya una ley en alguna parte. Entonces, en ese caso, haría ese campo varchar (8000) y lo llamaría un día. Mi pensamiento es el siguiente: ¿restricción real? varchar (x). ¿Sin restricción real? varchar (8000).
jcollum
24
Pensé que unos 30 caracteres eran buenos para los nombres de las ciudades, hasta que vi El Pueblo de Nuestra Señora la Reina de los Ángeles del Río de Porciúncula
StuartLC