Verwenden von MAX-Text oder einer spezifischeren, kleineren Schrift

22

Jemand war die Überprüfung meine DDL - Code für Tabellen erstellen und schlug vor, als sie sahen , sah ich mit VARCHAR(256)Feldern für Text erwarte ich ziemlich klein sein, wie ein Vorname oder was auch immer, dass ich immer nur verwenden VARCHAR(MAX)und verknüpft Warum Einsatz alles andere als varchar (max ) . Ich habe es gelesen, aber es schien veraltet zu sein, da es sich auf 2005 konzentrierte, und es schien keine wirkliche Rechtfertigung dafür zu bieten, potenziell bis zu 2 GB pro Zeile in allen Textfeldern zuzuweisen.

Wie sollte man in Bezug auf Leistung, Speicher usw. entscheiden, ob VARCHAR(MAX)für moderne Versionen von SQL Server ein spezifischerer oder ein kleinerer Typ verwendet werden soll? (z. B. 2008, 2012, 2014)

Phrancis
quelle

Antworten:

31

Soll ich immer (n)varchar(max)für Textspalten verwenden?

Nein.

Für SQL Server sollten die maxDatentypen nur angegeben werden, wenn es keine Alternative gibt. Man sollte stattdessen den richtigen Basistyp ( varcharoder nvarchar) auswählen und eine explizite maximale Länge angeben, die den zu speichernden Daten entspricht.

Der physische Speicher ist unabhängig davon, ob die Spalte als varchar(n)oder als typisiert ist, identisch varchar(max), sodass dies kein Problem darstellt.

Die Gründe, warum Sie sich nicht(n)varchar(max) überall entscheiden sollten , hängen von Funktionen, Planqualität und Leistung ab.

Eine erschöpfende Liste ist wahrscheinlich nicht praktikabel, aber unter anderem maxSpalten:

Eigenschaften

  • Erfordern eine separate Einschränkung, um eine maximale Länge zu erzwingen
  • Kann kein Schlüssel in einem Index sein (also auch keine eindeutigen Einschränkungen)
  • Verhindert möglicherweise Online-DDL (einschließlich Indexneuerstellungen und Hinzufügen einer neuen Nicht-Null-Spalte)
  • Werden in der Regel nicht für 'neuere' Funktionen unterstützt, z. B. Spaltenspeicher
  • Weitere Informationen zu Funktionen und Einschränkungen finden Sie in der Produktdokumentation. Das allgemeine Muster ist, dass es umständliche Einschränkungen und Restriktionen bei maxDatentypen gibt. Es sind nicht alle Einschränkungen und Nebenwirkungen dokumentiert.

Performance

  • Erfordern eine spezielle Behandlung in der Ausführungs-Engine, um die möglicherweise sehr große Größe zu berücksichtigen. In der Regel wird dabei ein weniger effizienter Codepfad mit einer Streaming-Schnittstelle verwendet
  • Kann ähnliche unerwartete Konsequenzen für externen Code (und andere SQL Server-Komponenten wie SSIS) haben, der auch für die Verarbeitung von Daten mit einer Größe von bis zu 2 GB vorbereitet sein muss
  • Es wird angenommen, dass die Speicherzuweisungsberechnungen 4000 Byte breit sind. Dies führt wahrscheinlich zu einer übermäßigen Speicherreservierung, die die Parallelität einschränkt und wertvolle Index- und Datenseiten aus dem Cache-Speicher verdrängt
  • Deaktivieren Sie mehrere wichtige Leistungsoptimierungen
  • Kann die Sperrdauer verlängern
  • Kann verhindern, dass der Optimierer einen (nicht dynamischen) Suchplan auswählt
  • Verhindern Sie, dass Filter in Scans und Suchvorgänge als Residuum verschoben werden
  • Kann den Tempdb-Druck und die Konflikte (versionsabhängig) erhöhen, da Variablen und Parameter wahrscheinlich auch so eingegeben werden, dass sie mit den Spaltendefinitionen maxübereinstimmen

Zusammenfassend gibt es so viele subtile (und unerwünschte) Nebenwirkungen der unnötigen Verwendung des maxBezeichners, dass es keinen Sinn macht, dies zu tun. Die geringfügige Bequemlichkeit der Verwendung einer einzigen Erklärung ist keine Entschädigung.

Bewerten Sie jeden Typ im Kontext, verwenden Sie den richtigen Basistyp ( varcharoder nvarchar) und eine sinnvolle explizite Länge.

Weitere Lektüre:

Paul White sagt GoFundMonica
quelle
8

Dies wird sich wie die Antwort eines Paranoiden anhören, aber es gibt nicht nur Überlegungen zu Speicherplatz und Leistung.

Die Datenbank selbst kontrolliert ihre Clients nicht und es kann nicht davon ausgegangen werden, dass Clients Benutzereingaben immer sicher einfügen. Dies gilt auch dann, wenn eine Datenbank nur für eine .NET-Anwendung entwickelt wurde, die Entity Framework verwendet, um Transaktionen zu kapseln und parametrisierte Abfragen sicherzustellen systematisch eingesetzt werden, kann man nicht wissen, dass es immer so sein wird.

Ich würde nicht genau wissen, wie das geht, aber wenn Sie alle Textfelder ausfüllen varchar(max), wenn ein Client Bobby Tables- Probleme hat und / oder die Parameter Ihrer gespeicherten Prozeduren ebenfalls varchar(max)sind, machen Sie es einem Angreifer leichter, darauf zu kommen Ein gültiger, aber clever böser Parameterwert, der Dinge tun kann, die Clients eigentlich nicht tun sollten - was auch immer das ist.

Durch die Begrenzung der Länge zu dem, was Sie wirklich brauchen, sind Sie nicht abschirmt , sich von diesen klugen Angriffe (ich bin nicht einmal sicher , was es tatsächlich genannt, ich erinnere mich nur darüber vor einiger Zeit zu lesen), aber Sie sagen nicht " Versuchen Sie, mir ein Skript mit 2 GB zur Ausführung zu geben.

Mathieu Guindon
quelle
Was es heißt, ist wahrscheinlich "Injection" ("SQL Injection", genauer gesagt).
Andriy M
@AndriyM Ja, aus irgendeinem Grund habe ich an SQL- Kürzungsangriffe gedacht (MS scheint den von mir mit einem Lesezeichen versehenen Link entfernt zu haben), aber das nutzt im Grunde genommen die varchar(not-max)Parameter aus, also habe ich mir hier einen Fuß in den Mund gesteckt. Aber ja, SQL Injection wäre hier anwendbar. Vielleicht sollte ich diese Antwort ein wenig umformulieren.
Mathieu Guindon