¿Cuáles son las mejores prácticas actuales sobre el tamaño de varchar en SQL Server?

12

Estoy tratando de entender la mejor manera de decidir qué tan grandes deben ser las columnas varchar, tanto desde el punto de vista del almacenamiento como del rendimiento.

Rendimiento
De mi investigación, pareceese varchar (max) solo debe usarse si realmente lo necesita; es decir, si la columna debe acomodar más de 8000 caracteres, una razón es la falta de indexación (aunque sospecho un poco de la indexación en los campos varchar en general. Sin embargo, soy bastante nuevo en los principios de DB, así que tal vez eso sea infundado ) y compresión (más una preocupación de almacenamiento). De hecho, en general, la gente parece recomendar solo usar lo que necesita, al hacer varchar (n) ... el sobredimensionamiento es malo, porque las consultas deben tener en cuenta el tamaño máximo posible. Pero también se ha dicho que el motor usará la mitad del tamaño indicado como una estimación del tamaño real promedio de los datos. Esto implicaría que uno debería determinar, a partir de los datos, cuál es el tamaño promedio, duplicarlo y usarlo como n. Sin embargo, para datos con una variabilidad muy baja pero no nula, Esto implica un sobredimensionamiento de hasta 2x sobre el tamaño máximo, lo que parece mucho, pero tal vez no lo sea. Se apreciarán las ideas.

Almacenamiento
Después de leer cómo funciona el almacenamiento en fila frente a fuera de fila, y teniendo en cuenta que el almacenamiento real se limita a los datos reales, en realidad me parece que la elección de n tiene poca o ninguna relación con el almacenamiento (además asegurándose de que sea lo suficientemente grande como para contener todo). Incluso el uso de varchar (max) no debería tener ningún impacto en el almacenamiento. En cambio, un objetivo podría ser limitar el tamaño real de cada fila de datos a ~ 8000 bytes si es posible. ¿Es una lectura precisa de las cosas?

Contexto
Algunos de nuestros datos de clientes fluctúan un poco, por lo que generalmente hacemos columnas un poco más anchas de lo que necesitan ser, digamos 15-20% más grandes, para esas columnas. Me preguntaba si había otras consideraciones especiales; por ejemplo, alguien con quien trabajo me dijo que usara 2 ^ n - 1 tamaños (aunque no he encontrado evidencia de que sea algo ...)

Estoy hablando de la creación de la tabla inicial. Un cliente nos dirá que van a comenzar a enviarnos una nueva tabla y nos enviarán datos de muestra (o solo el primer conjunto de datos de producción), que observaremos y haremos una tabla de nuestro lado para guardar los datos. Queremos hacer la tabla de nuestro lado para manejar las importaciones futuras, así como lo que está en la muestra. Pero, ciertas filas están obligadas a alargarse, por lo que las rellenamos.

La pregunta es cuánto y ¿hay pautas técnicas?

aristotle2600
fuente
MongoDB utiliza la asignación de disco 2 ^ n para un documento. SQL Server no usa esta estrategia.
Michael Green

Respuestas:

19

Independientemente del tipo de datos específico, debe poder almacenar lo que la aplicación solicite que se almacene. No puede especificar algo más pequeño que el tamaño máximo de lo que realmente se guardará.

Tampoco es necesario, ni desea, especificar una longitud de columna mayor que el tamaño real máximo que se almacenará por una variedad de razones: asignación de memoria de consulta, potencialmente llenando el tamaño máximo de fila y sin dejar espacio para agregar columnas en el futuro, etc.

Es cierto que la cadena de longitud variable y las columnas binarias no tienen la implicación de almacenamiento que tienen los tipos de datos de longitud fija (cadena / binario / numérico / fecha / etc.) (aunque algunas de esas implicaciones pueden anularse mediante la compresión de datos o el uso de la SPARSEdefinición de columna opción). Sin embargo, como señaló, incluso si no existe una implicación de almacenamiento directo, todavía existe la implicación de rendimiento de sobreestimar la memoria requerida para las consultas.

Ser sensible. Usa sólo lo que necesites. Se pueden tener en cuenta si existe una alta probabilidad de que la longitud de la columna deba aumentar en el futuro cercano, pero tenga en cuenta que es más fácil expandir el tamaño de una columna que reducir el tamaño. Sí, se involucrará algo de trabajo, pero dado que ese trabajo es simplemente "potencial", mientras que las implicaciones de sobredimensionamiento del rendimiento son "reales", a menudo es mejor definir columnas en función de lo que realmente necesita, no de lo que tal vez -sorta cree que podría necesitar en el futuro. Muchos cambios de los que se habla nunca suceden y, a menudo, los cambios necesarios no se pueden prever. Ve con lo que sabes.

En cambio, un objetivo podría ser limitar el tamaño real de cada fila de datos a ~ 8000 bytes si es posible.

No estoy exactamente seguro de lo que estás haciendo aquí. SQL Server lo limitará físicamente a poco más de 8000 bytes. El uso de tipos LOB - VARCHAR(MAX), NVARCHAR(MAX), VARBINARY(MAX), XML, y el desuso TEXT, NTEXTy IMAGEtipos - permiten ir más allá de ese límite para el tamaño de la página, pero eso es sólo debido a la colocación de un puntero (16 o más bytes, dependiendo del tipo, y dependiendo de la tamaño del valor que se almacena fuera de la fila cuando se usan los MAXtipos). El límite físico real de la página de datos no cambió.

Su objetivo debe ser utilizar la menor cantidad de espacio físico para almacenar lo que la aplicación / negocio necesita almacenar sin romperse o truncarse de modo que el valor incompleto pierda significado o cause problemas aguas abajo. Si necesita almacenar una cosita de 12,000 caracteres, úsela VARCHAR(MAX)porque eso es lo que necesita. Si está almacenando un número de teléfono o un código postal, entonces no sería prudente usarlo VARCHAR(100)e irresponsable VARCHAR(MAX).

algunos de nuestros datos de clientes fluctúan un poco, por lo que generalmente hacemos columnas un poco más anchas de lo que necesitan ser, digamos 15-20% más grandes, para esas columnas. Me preguntaba si había otras consideraciones especiales;

¿No tienen todos los sistemas al menos algunos datos que fluctúen? Cualquier sistema que almacene el nombre de una persona calificaría, ¿verdad? Hay una variación bastante grande en la longitud de los nombres. Y luego tienes a alguien como Prince y cambia su nombre a un símbolo y ahora tienes un problema completamente diferente que no es la longitud. Así es como son las cosas.

Pero, para jugar al abogado del diablo por un momento: ¿cómo puede el valor "15-20% mayor de lo que se necesita" no ser el valor real necesario ? Digamos que hay una discusión sobre agregar una nueva columna, y alguien sugiere 50 caracteres, luego alguien más dice: "bueno, 20% más es 60, así que hagamos 60 porque alguien podría tener 60". Si es cierto que un cliente podría tener 60, entonces 60 es, y siempre fue, el valor real necesario, y 50 estuvo equivocado todo el tiempo.

Por supuesto, ayudaría si hubiera alguna indicación sobre la fuente de los datos porque:

  1. si crea "URL" 1024 y alguien necesita 1060, entonces debe ser 1060 (de manera similar, si VARCHARcrea URL y recibe quejas de que está confundiendo caracteres Unicode que ahora están permitidos en los nombres de dominio, entonces tenía que serlo NVARCHAR), pero
  2. si alguien quiere agregar 1000 caracteres a un campo de comentario de límite de 500 caracteres, entonces solo necesita ser 500. Las personas pueden ser menos detalladas en los comentarios (un gran desafío para mí ;-), pero ProductSKUmejor ser lo suficientemente grande para todos de las SKU del cliente.

Estoy hablando de la creación de la tabla inicial. Un cliente nos dirá que van a comenzar a enviarnos una nueva tabla y nos enviarán datos de muestra (o solo el primer conjunto de datos de producción), que observaremos y haremos una tabla de nuestro lado para guardar los datos. Queremos hacer la tabla de nuestro lado para manejar las importaciones futuras, así como lo que está en la muestra. Pero, ciertas filas están obligadas a alargarse, por lo que las rellenamos. La pregunta es cuánto y ¿hay pautas técnicas?

Estás haciendo muchas suposiciones aquí. Claro que algunos campos pueden crecer. Pero, de nuevo, puede que no. O, algunos podrían hacerse más pequeños. Algunos pueden cambiar de no ser Unicode a ser Unicode (una vez que se dan cuenta de que el mundo se está volviendo más pequeño y no se puede suponer que los apellidos solo tendrán caracteres ASCII / inglés de EE. UU. Básicos). O podrían dejar de enviar un campo. O pueden agregar uno o más campos en el futuro. Cualquier combinación de esta y otras cosas. Entonces, ¿por qué centrarse solo en VARCHARcolumnas? ¿Qué sucede si actualmente están enviando un INTvalor y en un año o dos alcanzan el valor máximo y comienzan a enviar un valor BIGINT? ¿Qué pasa si tienen un campo de "estado" con valores 0 - 5. ¿Vas a asumirINTque está "acolchado", ya que permite el crecimiento, pero probablemente debería serlo TINYINT.

Lo único que puede predecir con seguridad es que tratar de predecir cómo cambiarán los datos de sus clientes será un error con más frecuencia de lo que es correcto. Y estar en lo correcto es cuestión de suerte / coincidencia (si no es suerte, entonces solo juega a la lotería;).

Entonces la pauta es:

  1. No pierdas tiempo y energía en tratar de responder una pregunta sin respuesta.
  2. En cambio, concéntrese en obtener tanta información como sea posible con respecto a los datos reales de su cliente, y continúe con eso (es decir, toma de decisiones basada en datos ;-).

Ya tienes datos de ejemplo, genial. Pero, no olvide que también tiene la información de contacto de su cliente: teléfono y / o correo electrónico. ¡Contáctales! Pídales sus especificaciones de datos (al igual que su sistema, los datos actualmente en su sistema pueden tener una longitud máxima de 35, pero su sistema lo tiene definido como VARCHAR(50), y su sistema aceptará hasta esa longitud, en cuyo caso debe usar 50) Y pregúnteles si tienen algún plan a corto plazo para cambiar y de esos tipos de datos (tipo y / o tamaño).

Solomon Rutzky
fuente
1
Estoy de acuerdo con Solomon, @ Aristotle2600; sin embargo, es posible que desee consultar mi respuesta a una pregunta sobre las diferencias entre ay varchar(255)a varchar(256)para algunas consideraciones adicionales
Max Vernon
Gracias, tenía la impresión de que sería algo así, y "usar solo lo que necesita" es una buena práctica de gestión de recursos en general. Pero, algunos de nuestros datos de clientes fluctúan un poco, por lo que generalmente hacemos columnas un poco más anchas de lo que necesitan ser, digamos 15-20% más grandes, para esas columnas. Me preguntaba si había otras consideraciones especiales; por ejemplo, alguien con quien trabajo me dijo que usara 2 ^ n - 1 tamaños (aunque no he encontrado evidencia de que sea algo ...). Pero parece que no hay nada más que mantener las cosas lo más pequeñas posible.
aristotle2600
1
@ aristotle2600 No estoy seguro de cómo aplicar "2 ^ n - 1", pero aún tendría que preguntar: ¿es teóricamente posible hacer algo más grande de lo necesario ? ¿No que el 15-20% mayor tamaño sea el tamaño que necesita ser para no romper? ;-). Estoy seguro de que ayudaría si fuera más explícito en la fuente de los datos, porque a) si crea la "URL" 1024 y alguien necesita 1060, entonces debe ser 1060, pero b) si alguien quiere agregar 1000 caracteres a un campo de comentario de límite de 500 caracteres, entonces solo necesita ser 500. Las personas pueden ingresar menos en los comentarios, pero es mejor que el SKU del producto sea lo suficientemente grande.
Solomon Rutzky
@ aristotle2600 Acabo de agregar algunos de sus comentarios aquí en la pregunta, ya que proporcionan un buen contexto. También agregué cosas al final de mi respuesta :)
Solomon Rutzky
¡Muchas gracias por su respuesta! Sí, los nombres y las direcciones fluctúan. En cuanto a la paradoja cada vez mayor del 20%, entiendo lo que quieres decir, pero estoy hablando de la creación de la tabla inicial. Un cliente nos dirá que van a comenzar a enviarnos una nueva tabla y nos enviarán datos de muestra (o solo el primer conjunto de datos de producción), que observaremos y haremos una tabla de nuestro lado para guardar los datos. Queremos hacer la tabla de nuestro lado para manejar las importaciones futuras, así como lo que está en la muestra. Pero, ciertas filas están obligadas a alargarse, por lo que las rellenamos. La pregunta es cuánto y ¿hay pautas técnicas?
aristotle2600