MySQL - varchar Länge und Leistung

19

Ist die Angabe der VARCHARGröße für die Leistung sinnvoll? Gibt es einen Geschwindigkeitsunterschied zwischen VARCHAR(50)und VARCHAR(255)? Oder ist die Definition der Länge eine logische / konstruktive Einschränkung?

Sonique
quelle

Antworten:

31

Dies ist eine sehr häufige "Prüfungs / Interview-Frage". Ich werde so gut ich kann antworten:

In den Standardzeilenformaten für InnoDB und MyISAM (dynamisch / kompakt) speichern a VARCHAR(50)und a VARCHAR(255)den Zeichenfolgentext auf dieselbe Weise - 1 Byte für die Länge und die tatsächliche Zeichenfolge mit 1 bis 4 Byte pro Zeichen (abhängig von der Kodierung und das tatsächlich gespeicherte Zeichen).

Wenn ich mich richtig erinnere, erinnere ich mich tatsächlich an jemanden, der das Datenwörterbuch mit einem hexadezimalen Editor geändert hat, um so etwas wie a VARCHAR(50)in a zu ändernVARCHAR(100) , sodass dies dynamisch erfolgen kann (normalerweise erfordert dies eine Tabellenrekonstruktion). Und das war möglich, weil die eigentlichen Daten von dieser Änderung nicht betroffen waren.

Das stimmt nicht mit VARCHAR(256) , denn dann werden immer 2 Bytes (mindestens) für die Länge benötigt.

Das heißt also, wir sollten es immer tun VARCHAR(255), oder? Nein. es gibt mehrere Gründe.

Während InnoDB möglicherweise ein Varchar dynamisch speichert, gilt dies nicht für andere Engines. MyISAM hat ein Format mit fester Zeilengröße und MEMORY-Tabellen haben immer eine feste Größe. Sollten wir uns um diese anderen Motoren kümmern? Ja, das sollten wir, denn auch wenn wir sie nicht direkt verwenden, werden MEMORY-Tabellen sehr häufig für Zwischenergebnisse verwendet (temporäre Tabellen im Speicher) , und da die Ergebnisse nicht im Voraus bekannt sind, muss die Tabelle mit der maximalen Größe erstellt werden möglich - VARCHAR(255)wenn das unser typ ist. Wenn Sie über den verschwendeten Speicherplatz nachdenken können, reserviert MEMORY bei Verwendung der MySQL- 'utf8' charsetCodierung 2 Bytes für die Länge + 3 * 255 Bytes pro Zeile(für Werte, die in InnoDB nur wenige Bytes benötigen dürfen). Das ist fast 1 GB bei einer Million Tischen - nur für den VARCHAR. Dies führt nicht nur zu unnötiger Speicherbelastung, sondern kann auch dazu führen, dass Aktionen auf der Festplatte ausgeführt werden, wodurch sie möglicherweise tausendfach verlangsamt wird. Dies alles aufgrund einer schlechten Auswahl des definierten Datentyps (unabhängig vom Inhalt).

Dies hat auch Konsequenzen für InnoDB. Die Indexgröße ist auf 3072 Byte und einspaltige Indizes auf 767 Byte * beschränkt. Daher ist es sehr wahrscheinlich, dass Sie einVARCHAR(255) Feld nicht vollständig indizieren können (vorausgesetzt, Sie verwenden utf8 oder eine andere variable Längencodierung).

Darüber hinaus beträgt die maximale Inline- Zeilengröße für InnoDB eine halbe Seite (ca. 8000 Byte), und Felder mit variabler Länge wie BLOB oder varchar können außerhalb der Seite gespeichert werden, wenn sie nicht auf die halbe Seite passen . Das hat einige Konsequenzen in der Leistung (manchmal gut, manchmal schlecht, abhängig von der Verwendung), die nicht ignoriert werden können. Dies verursachte eine gewisse Verrücktheit zwischen den Formaten COMPACT und DYNAMIC. Siehe zum Beispiel: Fehler 1118: Zeilengröße zu groß. utf8 innodb

Last but not least, wie @ypercube mich erinnert hat, kann mehr als 1 Byte für die Länge erforderlich sein, auch wenn Sie verwenden VARCHAR(255), da die Definition in Zeichen ist, während die Länge Bytes speichert. Zum Beispiel REPEAT('ñ', 255)hat utf8 mehr als 2 ^ 255 Bytes, daher würde es mehr als 1 Byte benötigen, um seine Länge zu speichern:

mysql> SELECT LENGTH(REPEAT('ñ', 255));
+---------------------------+
| LENGTH(REPEAT('ñ', 255))  |
+---------------------------+
|                       510 |
+---------------------------+
1 row in set (0.02 sec)

mysql> SELECT CHAR_LENGTH(REPEAT('ñ', 255));
+--------------------------------+
| CHAR_LENGTH(REPEAT('ñ', 255))  |
+--------------------------------+
|                            255 |
+--------------------------------+
1 row in set (0.00 sec)

Der allgemeine Ratschlag lautet daher , den kleinstmöglichen Typ zu verwenden , da dies möglicherweise zu Leistungs- oder Verwaltungsproblemen führen kann. A VARCHAR(100)ist besser als VARCHAR(255)(obwohl a VARCHAR(20)besser wäre), auch wenn Sie die genaue Länge nicht kennen. Versuchen Sie konservativ zu sein, da Sie die Definition später jederzeit ändern können, es sei denn, die Tabelle ist zu groß.

Aktualisieren: Aufgrund der zunehmenden Beliebtheit von Strings mit variabler Länge, zum Beispiel bei der Verwendung von Emojis, hat Oracle in diesen Fällen auf eine verbesserte Leistung gedrängt. In den neuesten MySQL-Versionen (5.6, 5.7) wurde InnoDB als Standard-Engine für interne und explizite temporäre Tabellen festgelegt, sodass Felder mit variabler Länge jetzt erstklassige Bürger sind. Das bedeutet, dass es möglicherweise weniger Gründe gibt, Zeichenlängen zu beschränken (die aber immer noch existieren).

(*) Zweites Update : large_prefix_index ist jetzt standardmäßig in den neuesten MySQL-Versionen (8.0) aktiviert. Dies gilt jedoch weiterhin für ältere Versionen oder wenn Sie ältere Innodb-Datei- / Zeilenformate (außer dynamisch oder komprimiert) verwenden Standardmäßig können einzelne Spaltenindizes bis zu 3072 Byte groß sein.

jynus
quelle
kleines Update: MySQL-8.0.13 + verwendet TempTable standardmäßig für temporäre Tabellen , die eine effiziente Speicherung für Varchars hat.
danblack
0

Vergessen Sie das 1- versus 2-Byte-Präfix VARCHARs.

  • Dies wirkt sich nur geringfügig auf die Leistung aus.
  • Es ist "2" öfter als die offensichtliche Regel sagt.

Die Frage zu 255 wurde schon oft gestellt und beantwortet.

  • Zu viele lange VARCHARskönnen zum Scheitern von führen CREATE TABLE.
  • Aus temporären Tabellen können MEMORYTabellen werden, aus denen VARCHARswird VARCHAR. Dies bedeutet zum Beispiel, dass VARCHAR(255) CHARACTER SET utf8mb4eine feste Länge von 1020 Bytes gewünscht wird. (Dies wird fehlschlagen und zur Verwendung von MyISAM verkommen.)

Fazit: Verwenden Sie nicht blind 255 (oder 256); Mach, was für das Schema Sinn macht.

Rick James
quelle