web-dev-qa-db-fra.com

EF Code First utilise nvarchar (max) pour toutes les chaînes. Cela affectera-t-il les performances des requêtes?

J'ai créé des bases de données en utilisant Entity Framework Code First; les applications fonctionnent et en général, je suis assez satisfait de ce que Code First me permet de faire. Je suis d'abord programmeur et second DBA, par nécessité. Je lis sur DataAttributes pour décrire plus en C # ce que je veux que la base de données fasse; et ma question est: quelle pénalité vais-je manger en ayant ces chaînes nvarchar(max) dans ma table (voir l'exemple ci-dessous)?

Il y a plusieurs colonnes dans ce tableau particulier; en C # ils sont définis comme tels:

    [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; }

Je m'attends à interroger et/ou trier en fonction du nom, de la source, du généré et de l'écrit. Je m'attends à ce que le nom et la source aient une longueur de 0 à 50 caractères, parfois jusqu'à 150. Je m'attends à ce que ce tableau commence assez petit (<100 000 lignes), mais croît considérablement au fil du temps (> 1 m de lignes). De toute évidence, le message peut être petit ou grand et ne sera probablement pas contesté.

Ce que je veux savoir, y a-t-il un impact sur les performances pour mes colonnes Nom et Source définies comme nvarchar(max) alors que je ne m'attends jamais à ce qu'elles dépassent 150 caractères?

29
Nate

Les éléments de données nvarchar (max) plus volumineux (plus de 8 000 octets environ) déborderont sur le stockage de texte et nécessiteront des E/S supplémentaires. Les petits articles seront stockés en ligne. Il existe des options qui contrôlent ce comportement - voir ceci article MSDN pour plus de détails.

S'il est stocké en ligne, il n'y a pas de surcharge significative de performances d'E/S; il peut y avoir une surcharge de CPU supplémentaire lors du traitement du type de données, mais cela est probablement mineur.

Cependant, laisser les colonnes nvarchar (max) traîner dans la base de données là où elles ne sont pas nécessaires est une forme plutôt mauvaise. Il a une certaine surcharge de performance et souvent les tailles de données sont très utiles pour comprendre un tableau de données - par exemple, une colonne varchar de 50 ou 100 caractères de large est probablement une description ou un champ de texte libre où celui qui est (disons) 10-20 caractères est probablement un code. Vous seriez surpris du sens que l'on a souvent à déduire d'une base de données à travers des hypothèses comme celle-ci.

Travailler dans l'entrepôt de données, aussi souvent qu'absence sur des systèmes hérités mal pris en charge ou documentés, avoir un schéma de base de données facile à comprendre est très utile. Si vous considérez la base de données comme l'héritage de l'application, essayez d'être gentil avec les personnes qui vont l'hériter de vous.

24

Bien que cela ne réponde pas à votre question spécifique, cela peut vous empêcher d'avoir à poser la question en premier lieu: il est possible de définir une longueur sur vos variables de chaîne dans votre classe de modèle C #, ce qui entraînera Entity Framework à générer du SQL qui utilise un type nvarchar de longueur fixe (par exemple nvarchar(50)), au lieu de nvarchar(max).

Par exemple, au lieu de:

public string Name { get; set; }

Vous pouvez utiliser:

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

Vous pouvez également forcer le type à être varchar au lieu de nvarchar, si vous le souhaitez, comme suit:

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

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

18
Jon Schneider

Indexer la plus grande préoccupation. De BOL:

Colonnes appartenant aux types de données d'objets volumineux (LOB) ntext, text, varchar(max), nvarchar(max), varbinary(max), xml ou image ne peuvent pas être spécifiés comme colonnes clés pour un index.

Si vous ne pouvez pas indexer correctement, vous allez avoir des requêtes lentes. Et du point de vue de l'intégrité des données, avoir nvarchar(max) permettra de mettre plus de mauvaises données dans un champ que de spécifier la limite.

9
HLGEM

Oui, le comportement EF par défaut dans le mappage de string à nvarchar(max) n'est pas bon. Dans EF 6, vous pouvez ajouter votre propre convention personnalisée pour remplacer ce comportement par votre propre mappage par défaut préféré.

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

    base.OnModelCreating(modelBuilder);
}

Remplacer OnModelCreating comme ci-dessus changera le mappage par défaut pour toutes les chaînes en varchar(200).

9
Paul