EF Code First verwendet für alle Zeichenfolgen nvarchar (max). Beeinträchtigt dies die Abfrageleistung?


29

Ich habe einige Datenbanken mit Entity Framework Code First erstellt. Die Apps funktionieren und im Allgemeinen bin ich ziemlich zufrieden mit dem, was ich mit Code First machen kann. Ich bin erstens ein Programmierer und zweitens ein Datenbankadministrator. Ich lese über DataAttributes, um in C # näher zu beschreiben, was die Datenbank tun soll. und meine Frage ist: Welche Strafe esse ich, wenn ich diese nvarchar(max)Saiten in meinem Tisch habe (siehe Beispiel unten)?

Diese Tabelle enthält mehrere Spalten. In C # sind sie wie folgt definiert:

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

Ich erwarte, basierend auf Name, Quelle, generiert und geschrieben abzufragen und / oder zu sortieren. Ich erwarte, dass Name und Quelle zwischen 0 und 50 Zeichen lang sind, gelegentlich bis zu 150. Ich erwarte, dass diese Tabelle recht klein anfängt (<100.000 Zeilen), aber mit der Zeit erheblich wächst (> 1 Mio. Zeilen). Offensichtlich kann die Nachricht klein oder groß sein und wird wahrscheinlich nicht abgefragt.

Was ich wissen möchte, gibt es einen Leistungstreffer für meine Namen- und Quellenspalten, nvarchar(max)wenn ich nie erwarte, dass sie länger als 150 Zeichen sind?


5
Sieht so aus, als müssten Sie entweder Attribute [MaxLength]oder anwenden [StringLength]. Einige zusätzliche mögliche negative Faktoren für zu breite Spalten werden in der Antwort von @ PaulWhite hier erwähnt
Martin Smith,

3
JA , varchar(max)überall zu verwenden schadet deiner Leistung - tu es nicht! Verwenden Sie geeignete Datentypen - verwenden Sie varchar(max) NUR, wenn Sie WIRKLICH mehr als 8000 Zeichen benötigen! (Ich habe noch nie gesehen, dass der Name oder die E-Mail-Adresse einer Person so lang ist!) - Siehe Was bringt es, VARCHAR (n) noch einmal zu verwenden? Für weitere Informationen
marc_s

@ marc_s Toller Link. Ich weiß, dass es die Leistung beeinträchtigt. Wenn ich meine eigenen Tabellen mit SQL definiere, verwende ich varchar (n). Meine Frage war eher, wie sehr es der Leistung schadet (obwohl mir klar ist, dass dies nicht ausdrücklich klar ist).
Nate

Antworten:


24

Größere nvarchar (max) -Datenelemente (über 8000 Byte oder so) werden in den Textspeicher übertragen und erfordern zusätzliche E / A. Kleinere Artikel werden in Reihe gespeichert. Es gibt Optionen, die dieses Verhalten steuern. Weitere Informationen finden Sie in diesem MSDN-Artikel .

Wenn in Reihe gespeichert, entsteht kein nennenswerter Aufwand für die E / A-Leistung. Die Verarbeitung des Datentyps verursacht möglicherweise zusätzlichen CPU-Overhead, dies ist jedoch wahrscheinlich geringfügig.

Nvarchar (max) -Spalten in der Datenbank liegen zu lassen, wo sie nicht benötigt werden, ist jedoch eine eher schlechte Form. Es hat einen gewissen Performance-Overhead und oft sind Datengrößen für das Verständnis einer Datentabelle sehr hilfreich - zum Beispiel ist eine 50 oder 100 Zeichen breite varchar-Spalte wahrscheinlich eine Beschreibung oder ein Freitextfeld, in dem eines, das (sagen wir) 10 ist. 20 Zeichen lang ist wahrscheinlich ein Code. Sie wären überrascht, wie viel Bedeutung man durch solche Annahmen oft aus einer Datenbank ableiten muss.

Die Arbeit in der Data-Warehousing-Umgebung, so oft es nicht auf schlecht unterstützten oder dokumentierten Altsystemen möglich ist, ist von großem Wert, wenn ein Datenbankschema leicht zu verstehen ist. Wenn Sie die Datenbank als das Erbe der Anwendung ansehen, versuchen Sie, nett zu den Leuten zu sein, die sie von Ihnen erben werden.


18

Obwohl dies Ihre spezifische Frage nicht beantwortet, kann es sein, dass Sie die Frage nicht unbedingt stellen müssen: Es ist möglich, eine Länge für Ihre Zeichenfolgenvariablen in Ihrer C # -Modellklasse festzulegen, wodurch Entity Framework SQL generiert, das verwendet einen nvarchar-Typ mit fester Länge (z. B. nvarchar(50)) anstelle von nvarchar(max).

Zum Beispiel anstelle von:

public string Name { get; set; }

Sie können verwenden:

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

Sie können auch die Art zwingen sein varcharstatt nvarchar, falls gewünscht, wie folgt:

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

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


2
Ich musste diese Antwort finden, um herauszufinden, dass EF Core das gleichzeitige Festlegen von Typ und Länge unterstützt ( varchar(50)). Für EF 6 ist jedoch erforderlich, was in dieser Antwort enthalten ist.
Sinjai

9

Indizierung der größten Sorge. Von BOL:

Spalten , die die große Objekt (LOB) Datentypen sind ntext, text, varchar(max), nvarchar(max), varbinary(max), xml, oder imagekönnen nicht als Schlüsselspalt für einen Index angegeben werden.

Wenn Sie nicht richtig indizieren können, werden Sie langsame Abfragen haben. Unter dem Gesichtspunkt der Datenintegrität nvarchar(max)wird es möglich sein, mehr fehlerhafte Daten in ein Feld einzutragen, als es die Angabe des Grenzwerts wäre.


9

Ja, das Standardverhalten von EF bei der Zuordnung stringzu nvarchar(max)ist nicht gut. In EF 6 können Sie eine eigene benutzerdefinierte Konvention hinzufügen, um dieses Verhalten mit Ihrer eigenen bevorzugten Standardzuordnung zu überschreiben.

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

    base.OnModelCreating(modelBuilder);
}

Durch Überschreiben OnModelCreatingwie oben wird die Standardzuordnung für alle Zeichenfolgen auf geändert varchar(200).


1
Dies funktioniert nicht in EF Core 1.0
Shittu Joseph Olugbenga

the default EF behavior in mapping string to nvarchar(max) is not goodDies scheint Ihre allgemeine Meinung zu sein. Kannst du erklären, warum das nicht gut ist? Oder Sie denken, EF ist kein Framework für Geschäftsanwendungen, bei denen Sie mit mehreren Sprachen arbeiten müssen? Da dies der gewünschte Spaltentyp für die Verarbeitung mehrerer Sprachen in der Datenbank ist.
Matthias Burger

1
@MatthiasBurger nvarchar (max) ist für die Leistung schrecklich, insbesondere in einer replizierten Umgebung. Es ist keine verallgemeinerte Meinung, es ist eine bekannte Tatsache.
user2966445

@ user2966445 sorry, ich denke da war ein missverständnis :) klar, maxist schrecklich. Aber wenn Sie mit mehreren Sprachen (und ihren unterschiedlichen Zeichensätzen) umgehen möchten, müssen Sie verwenden, nvarcharirre ich mich?
Matthias Burger

@MatthiasBurger Richtig, verwenden Sie nvarchar für verschiedene Zeichensätze, aber in diesem gesamten Beitrag geht es um Leistung und Feldlängen, nicht um die Verwendung von nvarchar vs. varchar.
user2966445
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.