Bedeutung der Varchar-Länge in der MySQL-Tabelle


112

Ich habe eine MySQL-Tabelle, in die Zeilen dynamisch eingefügt werden. Da ich mir der Länge der Saiten nicht sicher sein kann und nicht möchte, dass sie abgeschnitten werden, mache ich sie varchar (200), was im Allgemeinen viel größer ist, als ich brauche. Gibt es einen großen Leistungseinbruch, wenn ein Varchar-Feld viel länger als nötig ist?


Eine Tabelle mit einer einzelnen indizierten VARCHAR(255) utf8mb4Spalte mit ~ 150.000 Zeilen hatte eine Größe von 11,5 MB. Eine Tabelle mit einer VARCHAR(48) utf8mb4indizierten Spalte mit denselben Daten (maximale Länge 46 Zeichen) verwendete 4,5 MB. Es ist kein großer Unterschied bei Abfragen, es ist indiziert. Aber es summiert sich mit Abfrage-E / A und Dingen wie Datenbanksicherungen.
Code4R7

Antworten:


59

Nein, in dem Sinne, dass, wenn die Werte, die Sie in dieser Spalte speichern, immer (sagen wir) weniger als 50 Zeichen sind, die Spalte als dieselbe Leistung deklariert wird varchar(50)oder varchar(200)dieselbe Leistung hat.


9
Nicht genau das Richtige. Siehe Antwort von Bill Karwin
hejdav

5
Ich denke, eine Antwort wie sollte durch Dokumente, Benchmarks oder ähnliches unterstützt werden.
Gokhan Sari

301

Es gibt eine mögliche Auswirkung auf die Leistung: In MySQL MEMORYspeichern temporäre Tabellen und Tabellen eine VARCHARSpalte als Spalte mit fester Länge, die auf ihre maximale Länge aufgefüllt ist. Wenn Sie VARCHARSpalten entwerfen , die viel größer sind als die größte Größe, die Sie benötigen, verbrauchen Sie mehr Speicher als nötig. Dies wirkt sich auf die Cache-Effizienz, die Sortiergeschwindigkeit usw. aus.


33
+1. Ich habe auch einige JDBC-Treiber, die beim Einrichten von Puffern zum Abrufen von Zeilen genügend Speicherplatz für die maximale Größe reservieren. Unnötig zu erwähnen, dass dies viel Angst und Zähneknirschen verursacht, wenn ein Clown gerade Varchar (50000) gemacht hat, nur für den Fall, dass jemand einen wirklich großen Nachnamen hat :-)
paxdiablo

21
+1. Dies ist eine wichtige Auswirkung, und ich glaube, dies ist die eigentliche Antwort auf diese Frage.
Emre Yazici

6
Diese Antwort und die akzeptierte Antwort sind beide notwendig, um die richtige Antwort auf das OP zu verstehen.
kd8azz

2
Wenn eine solche MEMORYTabelle als zu groß angesehen wird, wird sie auf die Festplatte geschrieben, was zu einer erheblichen Leistungsverschlechterung führt.
Timo

1
Diese Antwort könnte mit der Angabe der Speicher-Engines zu tun haben (ich stelle fest, dass dev.mysql.com/doc/refman/8.0/en/… angibt, dass die temporären Tabellen ab MySQL 8 immer InnoDB sind; ändert dies etwas?) und mit Links zu Dokumenten, die die darin enthaltenen Behauptungen stützen. Nach dem, was ich von Ihrer Ausgabe auf Stack Exchange gesehen habe, glaube ich, dass Sie Recht hatten, als Sie dies geschrieben haben, aber die Dinge haben sich möglicherweise geändert, und Links würden sowohl ein gutes Beispiel für andere sein als auch den Rest von uns lehren, sie zu finden diese Art von Informationen für uns.
Mark Amery

14

VARCHAR ist ideal für die von Ihnen beschriebene Situation, da es für "variables Zeichen" steht - die Grenze, basierend auf Ihrem Beispiel, würde 200 Zeichen betragen, aber alles andere wird akzeptiert und füllt nicht die zugewiesene Größe der Spalte.

VARCHAR benötigt außerdem weniger Speicherplatz - die Werte werden als Präfix mit einer Länge von einem Byte oder zwei Bytes plus Daten gespeichert. Das Längenpräfix gibt die Anzahl der Bytes im Wert an. Eine Spalte verwendet ein Längenbyte, wenn Werte nicht mehr als 255 Bytes erfordern, zwei Längenbytes, wenn Werte möglicherweise mehr als 255 Bytes erfordern.

Weitere Informationen zum Vergleichen der MySQL CHAR- mit VARCHAR-Datentypen finden Sie unter diesem Link .


1
Jeder, der sich für MySQL-Speicher interessiert (über CHAR und VARCHAR), sollte den in dieser Antwort genannten Link lesen. Vielen Dank!
Pascal

14

Größe ist Leistung! Je kleiner die Größe, desto besser. Nicht heute oder morgen, aber eines Tages werden Ihre Tische auf eine Größe angewachsen sein, wenn es um schwerwiegende Engpässe geht, unabhängig davon, welches Design Sie entworfen haben. Sie können jedoch einige der potenziellen Engpässe in Ihrer Entwurfsphase vorhersehen, die wahrscheinlich zuerst auftreten, und versuchen, die Zeit zu verlängern, die Ihre Datenbank schnell und zufriedenstellend arbeitet, bis Sie Ihr Schema überdenken oder horizontal skalieren müssen, indem Sie weitere Server hinzufügen.

In Ihrem Fall gibt es viele Leistungslecks, auf die Sie stoßen können: Große Joins sind mit langen fast unmöglich varchar Spalten . Die Indizierung dieser Spalten ist ein echter Killer. Ihre Festplatte muss die Daten speichern. Eine Speicherseite kann weniger Zeilen enthalten und Tabellenscans sind viel langsamer. Auch der Abfrage-Cache wird Ihnen hier wahrscheinlich nicht weiterhelfen.

Sie müssen sich fragen: Wie viele Einfügungen pro Jahr können passieren? Was ist die durchschnittliche Länge? Benötige ich wirklich mehr als 200 Zeichen oder kann ich das in meinem Anwendungs-Frontend abfangen, selbst wenn ich Benutzer über die maximale Länge informiere? Kann ich die Tabelle in eine schmale Tabelle zum schnellen Indizieren und Scannen und eine andere zum Speichern zusätzlicher, weniger häufig benötigter Daten mit erweiterter Größe aufteilen? Kann ich die möglichen Varchar-Daten in Kategorien eingeben und so einige der Daten in einige kleinere, möglicherweise int- oder bool-artige Spalten extrahieren und die Varchar-Spalte auf diese Weise eingrenzen?

Hier kann man viel machen. Es kann am besten sein, eine erste Annahme zu treffen und dann Schritt für Schritt unter Verwendung realer gemessener Leistungsdaten neu zu entwerfen. Viel Glück.


+1 für die Auflistung von Designoptionen und die Untersuchung der Auswirkungen. Sehr hilfreich auch für meine Frage. stackoverflow.com/q/12083089/181638
Assad Ebrahim

5
Gibt es tatsächliche Auswirkungen auf die Leistung durch das Festlegen einer hohen maximalen Länge oder wird die Leistung nur durch die tatsächliche Größe bestimmt?
Poolie

5

Performance? Speicherplatz? Ja, aber es ist billig und reichlich. Wenn Ihre Datenbank nicht auf Terabyte skaliert, sind Sie wahrscheinlich in Ordnung.


Seltsam, dass diese Antwort sechs Jahre nach ihrer Veröffentlichung abgelehnt wurde und keiner der anderen. Scheint rachsüchtig und kleinlich. An dieser Antwort ist nichts Falsches. Moderatoren?
Duffymo

1
Wie gesagt, es beeinträchtigt die Leistung. Auch der Festplattenspeicher ist nicht kostenlos. Eine breitere Spalte bedeutet mehr Lese- / Schreibvorgänge auf der Festplatte (und der Zugriff auf die Festplatte ist langsam) und auch breitere Indizes, was deren Nützlichkeit verringert. Beide Dinge wirken sich negativ auf die Leistung aus. Vielleicht ist das in einer kleinen Datenbank vernachlässigbar, aber auf der Gigabyte / Terabyte-Skala wird es sicher eine Rolle spielen, wie Sie sagen. Für eine 100-Register-Tabelle spielt es keine Rolle.
Alejandro

5

Einige von Ihnen denken fälschlicherweise, dass a varchar(200)mehr Tabellengröße auf der Festplatte einnimmt als a varchar(20). Das ist nicht der Fall. Nur wenn Sie über 255 Zeichen hinausgehen, verwendet MySQL ein zusätzliches Byte, um die Länge der Felddaten zu bestimmen varchar.


9
Nicht so bei temporären Tabellen und MEMORYTabellen.
Leichtigkeitsrennen im Orbit

4
Jedes Mal, wenn Ihre ausgewählte Abfrage eine temporäre Tabelle verwendet (unter anderem Gruppierung und Reihenfolge nach Operationen), wird varchar (200) in char (200) konvertiert, und die Leistung leidet.
Jamie

1

Es kann zu Leistungseinbußen kommen - aber normalerweise nicht auf einem Niveau, das die meisten Benutzer bemerken würden.

Wenn die Größe jedes Felds im Voraus bekannt ist, weiß MySQL genau, wie viele Bytes sich zwischen den einzelnen Feldern / Zeilen befinden, und kann vorwärts blättern, ohne alle Daten zu lesen. Durch die Verwendung variabler Zeichen wird diese Optimierungsfähigkeit verringert.

Führt varchar aufgrund von Datenfragmentierung zu Leistungseinbußen?

Noch besser, char vs varchar .

Für die meisten Anwendungen ist beides in Ordnung - aber es gibt einen Unterschied, und für große Datenbanken gibt es Gründe, warum Sie sich für die eine oder andere entscheiden sollten.


0

Da varchar nicht nur char ist, basiert die Größe auf einem internen Feld, um die tatsächliche Länge und die Zeichenfolge selbst anzugeben. Die Verwendung von varchar (200) unterscheidet sich also nicht wesentlich von der Verwendung von varchar (150), außer dass Sie das Potenzial haben, mehr zu speichern.

Und Sie sollten überlegen, was bei einem Update passiert, wenn eine Zeile wächst. Aber wenn dies selten ist, sollte es Ihnen gut gehen.


0

Laut dem Datentypnamen handelt es sich um VARCHAR, dh um Datenspeicher mit variablen Zeichen. Die MySQL-Engine selbst weist den verwendeten Speicher gemäß den gespeicherten Daten zu, sodass nach meinem Wissen keine Leistungseinbußen auftreten.


0

Sie sollten versuchen, eine Varchar-Spalte genauso anzuzeigen wie eine Char-Spalte in den meisten Szenarien, und die Länge konservativ festlegen. Sie müssen nicht immer an den Var-Modifikator denken, sondern an etwas, das Ihre Entscheidung über die maximale Länge beeinflusst. Es sollte wirklich als Leistungshinweis gesehen werden, dass die mitgelieferten Saiten unterschiedlich lang sind.

Es ist keine Anweisung, die von Datenbank-Interna strikt befolgt werden muss, sie kann vollständig ignoriert werden. Seien Sie jedoch vorsichtig, da die Implementierung manchmal auslaufen kann (z. B. feste Länge und Polsterung), obwohl dies in einer idealen Welt nicht der Fall sein sollte.

Wenn Sie einen Varchar (255) haben, können Sie nicht garantieren, dass sich die Leistung unter allen Umständen immer anders verhält als ein Char (255).

Es kann einfach erscheinen, es auf etwas wie 255, 65535 usw. einzustellen, entsprechend den Hinweisen im Handbuch zu den Speicheranforderungen. Dies erweckt den Eindruck, dass jeder Wert zwischen 0 (ja, es ist eine Sache) und 255 die gleiche Auswirkung hat. Dies kann jedoch nicht vollständig garantiert werden.

Die Speicheranforderungen sind in der Regel wahr oder ein guter Indikator für anständige und ausgereifte persistente Speicher-Engines in Bezug auf den Zeilenspeicher. Es ist kein so starker Indikator für Dinge wie Indizes.

Es ist manchmal eine schwierige Frage, wie lang ein Stück Schnur genau sein sollte, um es auf die höchste Grenze zu bringen, von der Sie wissen, dass es innerhalb sein sollte, aber das hat keine Auswirkungen. Leider bleibt dies oft dem Benutzer überlassen und es ist wirklich etwas willkürlich. Man kann nicht wirklich sagen, dass man eine Zeichenfolge niemals überdimensioniert, weil es Fälle gibt, in denen man sich nicht ganz sicher ist.

Sie sollten sicherstellen, dass MySQL-Abfragen einen Fehler auslösen, wenn eine Zeichenfolge zu lang ist, anstatt sie abzuschneiden, damit Sie zumindest wissen, ob sie aufgrund von Fehleremissionen möglicherweise zu kurz ist. Das Ändern der Größe von Spalten zum Vergrößern oder Verkleinern kann eine teure DDL-Operation sein. Dies sollte beachtet werden.

Der Zeichensatz sollte auch dort berücksichtigt werden, wo Länge und Leistung ins Spiel kommen. Die Länge bezieht sich eher auf diese als auf Bytes. Wenn Sie beispielsweise utf8 verwenden (nicht MB4), ist varchar (255) wirklich varbinary (3 * 255). Es ist schwer zu wissen, wie sich solche Dinge wirklich entwickeln werden, ohne Tests durchzuführen und sich eingehend mit Quellcode / Dokumentation zu befassen. Aus diesem Grund besteht die Möglichkeit, dass eine zu lange Länge einen unerwartet aufgeblasenen Aufprall hat. Dies gilt nicht nur für die Leistung. Wenn Sie eines Tages den Zeichensatz einer Varchar-Spalte in einen größeren ändern müssen, könnten Sie ohne Rückgriff auf ein Limit stoßen, wenn Sie zulassen, dass unentgeltlich lange Zeichenfolgen vorhanden sind, die hätten vermieden werden können. Dies ist normalerweise ein ziemlich Nischenproblem, aber es kommt auf,

Wenn sich herausstellt, dass MAX (LENGTH (Spalte)) immer <64 ist (z. B. wenn entschieden wurde, dass die Eingabe nicht mit der Spaltendefinition übereinstimmt), Sie aber varchar (255) haben, gibt es eine Gute Chance, dass Sie in einigen Szenarien viermal mehr Speicherplatz benötigen als benötigt.

Dies kann Folgendes umfassen:

  • Verschiedene Motoren, einige können es völlig ignorieren.
  • Puffergrößen, zum Beispiel Aktualisieren oder Einfügen, müssen möglicherweise die vollen 255 zuweisen (obwohl ich den Quellcode nicht überprüft habe, um dies zu beweisen, ist dies nur eine Hypothese).
  • Indizes, dies wird sofort offensichtlich, wenn Sie versuchen, einen zusammengesetzten Schlüssel aus vielen varchar (255) -Spalten zu erstellen.
  • Zwischentabellen und möglicherweise Ergebnismengen. Angesichts der Funktionsweise von Transaktionen ist es möglicherweise nicht immer möglich, dass etwas die tatsächliche maximale Länge von Zeichenfolgen in einer Spalte im Gegensatz zum definierten Grenzwert verwendet.
  • Interne prädiktive Optimierungen können die maximale Länge als Eingabe verwenden.
  • Änderungen in den Datenbankimplementierungsversionen.

Als Faustregel gilt, dass ein Varchar nicht länger sein muss, als es ohnehin sein muss, Leistungsprobleme oder nicht. Ich empfehle daher, sich daran zu halten, wenn Sie können. Der ideale Ansatz besteht darin, sich mehr Mühe zu geben, um die Größe Ihrer Daten zu ermitteln, ein echtes Limit durchzusetzen oder das wahre Limit durch Fragen / Nachforschungen herauszufinden.

Wenn Sie nicht können, wenn Sie in Zweifelsfällen etwas wie varchar (255) tun möchten, empfehle ich, die Wissenschaft zu betreiben. Dies kann darin bestehen, die Tabelle zu duplizieren, die Größe der var char-Spalte zu verringern, dann die Daten aus dem Original in die Spalte zu kopieren und die Größe der Index- / Zeilendaten zu überprüfen (indizieren Sie auch die Spalte, versuchen Sie es auch als Primärschlüssel, der kann sich in InnoDB anders verhalten, da die Zeilen nach Primärschlüssel sortiert sind). Zumindest auf diese Weise wissen Sie, ob Sie einen Einfluss auf die E / A haben, der zu den empfindlichsten Engpässen zählt. Das Testen der Speichernutzung ist schwieriger, es ist schwierig, dies ausführlich zu testen. Ich würde empfehlen, potenzielle Worst-Cases zu testen (Abfragen mit vielen Zwischenergebnissen im Speicher, überprüfen Sie mit EXPLAIN auf große temporäre Tabellen usw.).

Wenn Sie wissen, dass die Tabelle nicht viele Zeilen enthält, Sie die Spalte nicht für Verknüpfungen, Indizes (insbesondere zusammengesetzte, eindeutige) usw. verwenden, werden Sie höchstwahrscheinlich nicht viele Probleme haben.

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.