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


29

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, puis 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 peine vais-je manger en ayant ces nvarchar(max)cordes 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 soient dans la longueur de 0 à 50 caractères, parfois jusqu'à 150. Je m'attends à ce que ce tableau commence assez petit (<100 000 lignes), mais augmente 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 de mes colonnes Nom et Source nvarchar(max)lorsque je ne m'attends pas à ce qu'elles dépassent 150 caractères?


5
Il semble que vous devez appliquer les attributs [MaxLength]ou [StringLength]. Certains autres facteurs négatifs possibles de colonnes trop larges sont mentionnés dans la réponse de @ PaulWhite ici
Martin Smith

3
OUI , utiliser varchar(max)partout nuit à votre performance - ne le faites pas! Utilisez les types de données appropriés - utilisez varchar(max) UNIQUEMENT si vous avez VRAIMENT besoin de plus de 8 000 caractères! (Je n'ai jamais vu le nom ou l'adresse e-mail d'une personne aussi longue!) - Voir Quel est l'intérêt d'utiliser VARCHAR (n) de plus? pour plus d'informations
marc_s

@marc_s Excellent lien. Je sais que cela nuit à la performance. Lorsque je définis mes propres tables avec SQL, j'utilise varchar (n). Ma question portait davantage sur les effets néfastes sur les performances (même si je me rends compte, comme indiqué, que ce n'était pas clairement clair).
Nate

Réponses:


24

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 - consultez cet 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 médiocre. Il y a une surcharge de performances 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 sont 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 précieux. 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.


18

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 varcharau lieu de nvarchar, si vous le souhaitez, comme suit:

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

Source: /programming/7341783/entity-framework-data-annotations-set-stringlength-varchar/7341920


2
Il a fallu trouver cette réponse pour me permettre de comprendre que EF Core prend en charge la définition du type et de la longueur en même temps ( varchar(50)), mais EF 6 nécessite le contenu de cette réponse.
Sinjai

9

Indexer la plus grande préoccupation. De BOL:

Les colonnes qui sont des gros objet (LOB) types de données ntext, text, varchar(max), nvarchar(max), varbinary(max), xml, ou imagene peuvent pas être spécifiées comme colonnes de clé 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

Oui, le comportement EF par défaut dans le mappage stringvers 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 OnModelCreatingcomme ci-dessus changera le mappage par défaut pour toutes les chaînes en varchar(200).


1
Cela ne fonctionne pas dans EF Core 1.0
Shittu Joseph Olugbenga

the default EF behavior in mapping string to nvarchar(max) is not goodcela semble être votre opinion générale. pouvez-vous expliquer pourquoi ce n'est pas bon? Ou, vous pensez, EF n'est pas un cadre pour les applications métier où vous devez travailler avec plusieurs langues? Parce que c'est le type de colonne souhaité pour gérer plusieurs langues sur la base de données.
Matthias Burger

1
@MatthiasBurger nvarchar (max) est horrible pour les performances, en particulier dans un environnement répliqué. Ce n'est pas une opinion généralisée, c'est un fait bien connu.
user2966445

@ user2966445 désolé, je pense qu'il y a eu un malentendu :) bien sûr, maxc'est horrible. Mais si vous voulez gérer plusieurs langues (et leurs différents jeux de caractères), vous devez utiliser nvarchar, ai-je tort?
Matthias Burger

@MatthiasBurger C'est exact, utilisez nvarchar pour différents jeux de caractères, mais tout ce post concerne les performances et la longueur des champs, pas l'utilisation de nvarchar contre varchar.
user2966445
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.