Usando texto MAX o más específico, tipo más pequeño


22

Alguien estaba revisando mi código DDL para crear tablas y sugirió que, cuando vieron que usaba VARCHAR(256)campos para texto, espero que sea bastante pequeño, como un nombre o lo que sea, que siempre debería usar VARCHAR(MAX)y vincular. Por qué usar cualquier cosa menos varchar (max ) . Lo leí pero parecía anticuado, ya que se estaba centrando en 2005, y no parecía ofrecer ninguna justificación real para asignar potencialmente hasta 2 GB por fila en todos los campos de texto.

Desde el punto de vista del rendimiento, el almacenamiento, etc., ¿cómo debería uno decidir si usar VARCHAR(MAX)o un tipo más pequeño y específico para las versiones modernas de SQL Server? (por ejemplo, 2008, 2012, 2014)

Respuestas:


31

¿Debo usar siempre (n)varchar(max)para columnas de texto?

No.

Para SQL Server, los maxtipos de datos solo deben especificarse cuando no hay alternativa. En su lugar, se debe elegir el tipo base correcto ( varcharo nvarchar) y especificar una longitud máxima explícita que sea apropiada para los datos que se almacenarán.

El almacenamiento físico es idéntico si la columna se escribe como varchar(n)o varchar(max), por lo que no es un problema.

Las razones para no elegir en (n)varchar(max)todas partes giran en torno a las características, la calidad del plan y el rendimiento.

Una lista exhaustiva probablemente no sea práctica, pero entre otras cosas, maxcolumnas:

Caracteristicas

  • Requerir una restricción separada para imponer una longitud máxima
  • No puede ser una clave en un índice (por lo que tampoco hay restricciones únicas)
  • Puede evitar el DDL en línea (incluidas las reconstrucciones de índice y la adición de una nueva columna no nula)
  • Por lo general, no son compatibles con las funciones 'más nuevas', por ejemplo, almacén de columnas
  • Consulte la documentación del producto para obtener características y limitaciones más específicas. El patrón general es que existen limitaciones y restricciones incómodas en torno a maxlos tipos de datos. No todas las limitaciones y efectos secundarios están documentados.

Actuación

  • Requiere un manejo especial en el motor de ejecución, para tener en cuenta el tamaño potencialmente muy grande. Por lo general, esto implica el uso de una ruta de código menos eficiente, con una interfaz de transmisión
  • Puede tener consecuencias imprevistas similares para el código externo (y otros componentes de SQL Server como SSIS), que también deben estar preparados para manejar datos de hasta 2 GB de tamaño
  • Se supone que tienen 4000 bytes de ancho en los cálculos de concesión de memoria. Es probable que esto conduzca a una reserva de memoria excesiva, lo que limita la concurrencia y elimina valiosas páginas de índice y datos de la memoria caché
  • Deshabilite varias optimizaciones de rendimiento importantes
  • Puede extender la duración del bloqueo
  • Puede evitar que el optimizador elija un plan de búsqueda (no dinámico)
  • Evita que los filtros se inserten en escaneos y se busque como residual
  • Puede aumentar la presión y la contención de tempdb (depende de la versión), ya que también es probable que las variables y los parámetros se tomen maxpara que coincidan con las definiciones de columna

En resumen, hay tantos efectos secundarios sutiles (e indeseables) de usar innecesariamente el maxespecificador que no tiene sentido hacerlo. La "conveniencia" menor de usar una sola declaración no es ningún tipo de compensación.

Evalúe cada tipo en contexto, use el tipo base correcto ( varcharo nvarchar) y una longitud explícita sensible.

Otras lecturas:


8

Esto se leerá como la respuesta de un paranoico, pero no solo hay consideraciones de almacenamiento y rendimiento.

La base de datos en sí misma no controla a sus clientes, y no se puede suponer que los clientes siempre inserten de forma segura la entrada del usuario, incluso si una base de datos está diseñada para usarse solo con una aplicación .net que usa Entity Framework para encapsular transacciones y garantizar consultas parametrizadas se usan sistemáticamente, no puedes saber que siempre será así.

No sabría exactamente cómo hacer esto, pero al hacer todos los campos de texto varchar(max), si un cliente tiene problemas con Bobby Tables y / o los parámetros de sus procedimientos almacenados también lo están varchar(max), entonces está facilitando que un atacante presente un valor de parámetro válido pero astutamente malvado que puede hacer cosas que los clientes no deben hacer, sea lo que sea.

Al limitar la longitud a lo que realmente necesita, no se está protegiendo de estos ataques inteligentes (ni siquiera estoy seguro de cómo se llama realmente, solo recuerdo haberlo leído hace un tiempo), pero no dice " adelante, intenta darme un script de 2GB para ejecutar "tampoco.


Lo que se llama es probablemente "inyección" ("inyección SQL", más específicamente).
Andriy M

@AndriyM sí, por alguna razón estaba pensando en ataques de truncamiento SQL (MS parece haber eliminado el enlace que había marcado), pero eso es básicamente explotar varchar(not-max)parámetros, así que me quedé un poco en la boca aquí. Pero sí, la inyección SQL sería aplicable aquí. Quizás debería reformular un poco esta respuesta.
Mathieu Guindon
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.