EF Code First usa nvarchar (max) para todas las cadenas. ¿Esto afectará el rendimiento de la consulta?


29

Tengo algunas bases de datos creadas usando Entity Framework Code First; las aplicaciones funcionan y, en general, estoy bastante contento con lo que Code First me permite hacer. Soy un programador primero, y un DBA segundo, por necesidad. Estoy leyendo sobre DataAttributes para describir mejor en C # lo que quiero que haga la base de datos; y mi pregunta es: ¿qué penalidad estaré comiendo al tener estas nvarchar(max)cadenas en mi mesa (ver ejemplo a continuación)?

Hay varias columnas en esta tabla en particular; en C # se definen como tales:

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    public string Name { get; set; }
    public string Message { get; set; }
    public string Source { get; set; }
    public DateTime Generated { get; set; }
    public DateTime Written { get; set; }

Espero consultar y / u ordenar según el Nombre, Fuente, Generado y Escrito. Espero que Nombre y Fuente tengan una longitud de 0-50 caracteres, ocasionalmente hasta 150. Espero que esta tabla comience bastante pequeña (<100k filas), pero crezca significativamente con el tiempo (> 1m filas). Obviamente, el mensaje puede ser pequeño o grande, y probablemente no será consultado.

Lo que quiero saber, ¿hay un impacto de rendimiento para mis columnas de Nombre y Fuente que se definen como nvarchar(max)cuando nunca espero que tengan más de 150 caracteres?


55
Se parece que necesitan aplicar ya sea [MaxLength]o [StringLength]atributos. Algunos posibles factores negativos adicionales de columnas demasiado anchas se mencionan en la respuesta de @ PaulWhite aquí
Martin Smith

3
, usar en varchar(max)todas partes perjudica su rendimiento , ¡no lo haga! Use los tipos de datos apropiados: ¡ Úselo varchar(max) SOLO si REALMENTE necesita más de 8000 caracteres! (¡Nunca he visto el nombre o el correo electrónico de una persona tan largo!) - Vea ¿Cuál es el punto de usar VARCHAR (n)? para más información
marc_s

@marc_s Gran enlace. Sé que daña el rendimiento. Cuando defino mis propias tablas con SQL, uso varchar (n). Mi pregunta era más sobre cuánto perjudica el rendimiento (aunque me doy cuenta de lo publicado que no estaba explícitamente claro).
Nate

Respuestas:


24

Los elementos de datos nvarchar (máx.) Más grandes (más de 8000 bytes) se extenderán al almacenamiento de texto y requerirán E / S adicionales. Los artículos más pequeños se almacenarán en fila. Hay opciones que controlan este comportamiento; consulte este artículo de MSDN para obtener más detalles.

Si se almacena en fila, no hay una sobrecarga de rendimiento de E / S significativa; puede haber una sobrecarga adicional de la CPU al procesar el tipo de datos, pero es probable que esto sea menor.

Sin embargo, dejar columnas nvarchar (max) alrededor de la base de datos donde no se necesitan es una forma bastante pobre. Tiene cierta sobrecarga de rendimiento y, a menudo, los tamaños de datos son bastante útiles para comprender una tabla de datos; por ejemplo, una columna varchar de 50 o 100 caracteres de ancho probablemente sea una descripción o un campo de texto libre donde uno es (digamos) 10- Es probable que 20 caracteres sean un código. Te sorprendería el significado que a menudo se tiene que inferir de una base de datos a través de suposiciones como esta.

Trabajar en el almacenamiento de datos, casi siempre en sistemas heredados mal respaldados o documentados, tener un esquema de base de datos que sea fácil de entender es bastante valioso. Si piensa en la base de datos como el legado de la aplicación, trate de ser amable con las personas que la heredarán de usted.


18

Aunque esto no responde a su pregunta específica, puede evitar que tenga que hacer la pregunta en primer lugar: es posible establecer una longitud en sus variables de cadena en su clase de modelo C #, lo que hará que Entity Framework genere SQL que utiliza un tipo nvarchar de longitud fija (p nvarchar(50). ej. ), en lugar de nvarchar(max).

Por ejemplo, en lugar de:

public string Name { get; set; }

Puedes usar:

[StringLength(50)]
public string Name { get; set; }

También puede forzar que el tipo sea en varcharlugar de nvarchar, si lo desea, de la siguiente manera:

[Column(TypeName = "VARCHAR")]
[StringLength(50)]
public string Name { get; set; }

Fuente: https://stackoverflow.com/questions/7341783/entity-framework-data-annotations-set-stringlength-varchar/7341920


2
Me llevó encontrar esta respuesta para permitirme descubrir que EF Core admite el tipo y la longitud de configuración al mismo tiempo ( varchar(50)), pero EF 6 requiere lo que hay en esta respuesta.
Sinjai

9

Indexando la mayor preocupación. De BOL:

Columnas que son de los tipos de datos de objetos grandes (LOB) ntext, text, varchar(max), nvarchar(max), varbinary(max), xml, o imageno pueden ser especificadas como columnas de clave para un índice.

Si no puede indexar correctamente, tendrá consultas lentas. Y desde una perspectiva de integridad de datos, tener nvarchar(max)permitirá que se coloquen más datos incorrectos en un campo que especificar el límite.


9

Sí, el comportamiento predeterminado de EF en la asignación stringa nvarchar(max)no es bueno. En EF 6 puede agregar su propia convención personalizada para anular este comportamiento con su propia asignación predeterminada preferida.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<string>()
        .Configure(s => s.HasMaxLength(200).HasColumnType("varchar") );

    base.OnModelCreating(modelBuilder);
}

Anular OnModelCreatingcomo se indica arriba cambiará la asignación predeterminada para todas las cadenas a varchar(200).


1
Esto no funciona en EF Core 1.0
Shittu Joseph Olugbenga

the default EF behavior in mapping string to nvarchar(max) is not goodEsta parece ser tu opinión generalizada. ¿Puedes explicar por qué esto no es bueno? ¿O cree que EF no es un marco para aplicaciones empresariales en las que necesita trabajar con varios idiomas? Porque ese es el tipo de columna deseado para manejar múltiples idiomas en la base de datos.
Matthias Burger

1
@MatthiasBurger nvarchar (max) es horrible para el rendimiento, especialmente en un entorno replicado. No es una opinión generalizada, es un hecho bien conocido.
user2966445

@ user2966445 lo siento, creo que hubo un malentendido :) claro, maxes horrible. Pero si desea manejar varios idiomas (y sus diferentes conjuntos de caracteres) debe usar nvarchar¿me equivoco?
Matthias Burger

@MatthiasBurger Eso es correcto, use nvarchar para diferentes conjuntos de caracteres, pero esta publicación completa trata sobre el rendimiento y la longitud de los campos, no sobre el uso de nvarchar contra varchar.
user2966445
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.