Auswirkungen auf die Leistung von MySQL VARCHAR-Größen

45

Gibt es in MySQL einen Leistungsunterschied zwischen den Varchar-Größen? Zum Beispiel varchar(25)und varchar(64000). Wenn nicht, gibt es einen Grund, nicht alle Varchars mit der maximalen Größe zu deklarieren, um sicherzustellen, dass Ihnen nicht der Raum ausgeht?

BenV
quelle
3
+1 Diese Frage gilt ähnlich für alle DBMS. Meiner Beobachtung nach neigen viele Varchargrößen dazu zu wachsen.
bernd_k
5
Nicht MySQL, aber dieser Blog-Beitrag von Depesz könnte Ihre Frage an PostgreSQL beantworten .
Xenoterracide

Antworten:

29

Sie müssen die Kompromisse zwischen der Verwendung von CHAR und VARCHAR erkennen

Bei CHAR-Feldern ordnen Sie genau das zu, was Sie erhalten. Beispielsweise weist CHAR (15) 15 Bytes zu und speichert diese, unabhängig davon, wie viele Zeichen Sie in das Feld eingeben. Die Manipulation von Zeichenfolgen ist einfach und unkompliziert, da die Größe des Datenfelds vollständig vorhersehbar ist.

Mit VARCHAR-Feldern erhalten Sie eine ganz andere Geschichte. Beispielsweise weist VARCHAR (15) dynamisch bis zu 16 Bytes, bis zu 15 Bytes für Daten und mindestens 1 zusätzliches Byte zum Speichern der Länge der Daten zu. Wenn Sie die Zeichenfolge 'Hallo' zum Speichern haben, die 6 Bytes und nicht 5 Bytes benötigt, muss bei der Zeichenfolgenmanipulation in jedem Fall eine Art Längenprüfung durchgeführt werden.

Der Kompromiss ist offensichtlicher, wenn Sie zwei Dinge tun:
1. Millionen oder Milliarden von Zeilen
speichern 2. Spalten indizieren, die entweder CHAR oder VARCHAR sind

Handel # 1

Offensichtlich hat VARCHAR den Vorteil, dass Daten mit variabler Länge kleinere Zeilen und damit kleinere physische Dateien erzeugen würden.

Handel # 2

Da CHAR-Felder aufgrund festgelegter Feldbreiten weniger Manipulation von Zeichenfolgen erfordern, sind Index-Lookups für CHAR-Felder im Durchschnitt 20% schneller als für VARCHAR-Felder. Dies ist keine Vermutung von meiner Seite. Das Buch MySQL Database Design and Tuning hat auf einer MyISAM-Tabelle etwas Wunderbares geleistet, um dies zu beweisen. Das Beispiel im Buch hat ungefähr Folgendes bewirkt:

ALTER TABLE tblname ROW_FORMAT=FIXED;

Diese Direktive zwingt VARCHARs, sich als CHARs zu verhalten. Ich habe dies bei meinem vorherigen Job im Jahr 2007 getan und eine Tabelle mit 300 GB erstellt und die Indexsuche um 20% beschleunigt, ohne etwas anderes zu ändern. Es funktionierte wie veröffentlicht. Es wurde jedoch ein fast doppelt so großer Tisch erstellt, aber das geht einfach auf Kompromiss Nr. 1 zurück.

Sie können die gespeicherten Daten analysieren, um festzustellen, was MySQL für die Spaltendefinition empfiehlt. Führen Sie einfach Folgendes für eine beliebige Tabelle aus:

SELECT * FROM tblname PROCEDURE ANALYSE();

Dadurch wird die gesamte Tabelle durchsucht und es werden Spaltendefinitionen für jede Spalte basierend auf den darin enthaltenen Daten, den minimalen Feldwerten, den maximalen Feldwerten usw. empfohlen. Manchmal muss man beim Planen von CHAR vs VARCHAR nur den gesunden Menschenverstand anwenden. Hier ist ein gutes Beispiel:

Wenn Sie IP-Adressen speichern, besteht die Maske für eine solche Spalte aus höchstens 15 Zeichen (xxx.xxx.xxx.xxx). Ich würde sofort zu CHAR (15) springen, da die Länge der IP-Adressen nicht allzu stark variiert und die zusätzliche Komplexität der String-Manipulation durch ein zusätzliches Byte gesteuert wird. Sie können immer noch eine PROCEDURE ANALYZE () für eine solche Spalte ausführen. Es kann sogar VARCHAR empfehlen. Mein Geld wäre in diesem Fall immer noch CHAR über VARCHAR.

CHAR vs VARCHAR-Probleme können nur durch ordnungsgemäße Planung gelöst werden. Mit großer Kraft geht große Verantwortung einher (Klischee aber wahr)

RolandoMySQLDBA
quelle
4
Wenn Sie IP-Adressen speichern, sehe ich keinen Grund, sie als etwas anderes als int zu speichern. Das ist alles, was eine IP-Adresse ist. Viele Sprachen haben eine Art ip2int-Funktion. Wenn Sie die Sicherheit eines Befehlszeilenaufrufs wünschen, ist es nicht schwierig, eine gespeicherte Prozedur zum Konvertieren von ABCD zu erstellen : A pow (256,3) + b pow (256,2) + c * 256 + d
atxdba 18.10.11
1
Ähm mehr auf den Punkt, ich denke, MySQL hat eine eigene IP2int-Funktion: INET_ATON
atxdba
3
@atxdba: In meiner Antwort geht es nur darum, CHAR vs VARCHAR zu verwenden. Ich verwende IP nur als Beispiel, weil seine Zeichenfolge näher bei 15 liegt. Daher ist das Abrunden einer stabilen CHAR-Größe zugunsten von VARCHAR nur ein Beispiel für die eigentliche Frage. Ihr Kommentar zur besseren Darstellung von IP-Adressen ist durchaus gültig und am sinnvollsten.
RolandoMySQLDBA
CHAR (15) weist 15 Zeichen zu , keine Bytes . Für utf8 sind das 45 Bytes .
Rick James
2
Dies ist zwar eine gute Antwort zum CHAR / VARCHAR-Vergleich, die Frage betraf jedoch verschiedene VARCHAR-Größen.
Collector
13

Die Antwort darauf ist eigentlich ziemlich komplex. Die kurze Version: Es gibt einen Unterschied .

  1. Beim Erstellen temporärer Tabellen zum Filtern von Ergebnissen (z. B. GROUP BYAnweisungen) wird die gesamte Länge zugewiesen.

  2. Das Wire-Protokoll (Senden von Zeilen an den Client) weist wahrscheinlich die größere Länge zu.

  3. Die Speicher-Engine implementiert möglicherweise / möglicherweise nicht einen richtigen Varchar.

Für (2) Ich gebe zu, dass das Wire-Protokoll nicht etwas ist, mit dem ich bestens vertraut bin, aber der allgemeine Ratschlag hier ist, zumindest einen minimalen Aufwand zu betreiben, um die Länge zu erraten.

Morgan Tocker
quelle
Es lohnt sich darauf hinzuweisen. MySQL 5.7 kann Werte in den Sortierpuffer packen (variable Länge). Weitere Informationen finden Sie
Morgan Tocker
9

Die meisten Antworten in diesem Thread sind 5 Jahre alt und wurden geschrieben, bevor InnoDB und utf8 Standardwerte waren. Also, lass mich von vorne anfangen ...

Wenn eine Abfrage eine interne temporäre Tabelle benötigt, versucht sie, eine MEMORYTabelle zu verwenden. MEMORY kann jedoch nicht verwendet werden, wenn

  • TEXT/ BLOBSpalten werden abgerufen, nicht einmal TINYTEXT.
  • VARCHAR größer als ein gewisser Betrag, wahrscheinlich 512 in der aktuellen Version.

Beachten Sie auch, dass VARCHARsin verwandelt werden CHARs. Also, VARCHAR(255)mit einem CHARACTER SET utf8auf 765 Bytes erweitert, unabhängig davon, was in der Spalte ist. Dann könnte dies ausgelöst werden:

  • Wenn die MEMORYTabelle größer als max_heap_table_size oder wird tmp_table_size , wird sie in MyISAM konvertiert und möglicherweise auf die Festplatte übertragen.

Also, VARCHAR(25)ist eher zu bleiben MEMORY, daher schneller. (255)ist nicht so gut und (64000)ist schlecht.

(In Zukunft wird es wahrscheinlich temporäre Tabellen geben InnoDB, und ein Teil dieser Antwort muss überarbeitet werden.)

Rick James
quelle
6

Eine varchar-Spalte mit dieser Größe erhöht die Wahrscheinlichkeit, dass bei Abfragen in der gesamten Tabelle temporäre Tabellen verwendet werden. Nach dem High Performance MySQL-Buch. Wenn das Optimierungsprogramm versucht, festzustellen, ob diese Abfrage im Arbeitsspeicher ausgeführt werden kann oder ob eine temporäre Tabelle erforderlich ist, wird die Zeilengröße anhand der Tabellendefinition überprüft, dh es wird aus Geschwindigkeitsgründen nicht versucht, festzustellen, wie viele der 64-KB-Zeichen vorhanden sind Sie verwenden tatsächlich. Aus diesem Grund empfehlen die Autoren, diese Definition nicht über die tatsächlich möglichen Werte in der Spalte hinaus auszudehnen. Wenn Sie sich auf mehr Abfragen in temporären Tabellen einstellen (selbst wenn die tatsächliche Datengröße in den Arbeitsspeicher passt), haben Sie offensichtlich jetzt E / A-Nachteile, die Sie hätten vermeiden können.

TechieGurl
quelle
Das ist eine sehr neue Perspektive. Wenn dies das Buch ist, auf das Sie sich beziehen ( amazon.com/MySQL-High-Availability-Building-Centers/dp/… ), geben Sie bitte die Seitenzahl des Buches in Ihre Antwort ein, da ich diese lesen möchte. +1 !!!
RolandoMySQLDBA
Dummkopf… Hohe LEISTUNG nicht verfügbar: amazon.com/High-Performance-MySQL-Optimization-Replication/dp/ ... Seitenzahl ist 236/237 Es wird erklärt, wie großzügig das Definieren einer varchar-Spalte sein kann. Denken Sie jedoch daran, dass dieses Buch zurückgeschrieben wurde, als 5.1 gerade erschienen war. Eine dritte Ausgabe kommt nächstes Jahr heraus, um alle GROSSEN Änderungen in 5.5 aufzunehmen, also wird sich das vielleicht ändern :)
TechieGurl
Auf Seite 236 wird die Sortierung erwähnt, die zu bestimmten Zeichensätzen gehört. Das könnte für VARCHAR ziemlich unangenehm sein. Auf Seite 237 zeigen die Einstellungen für die Client / Server-Kommunikation zusammen mit Abbildung 5-5 auf Seite 238 einen weiteren Grund. Der Prozess der Übersetzung von Zeichen läuft hin und her. Wieder ein böses Abenteuer für VARCHAR.
RolandoMySQLDBA
Obwohl in diesem Abschnitt nicht klargestellt wird, dass MySQL die Größe erzeugen soll, wissen wir, dass wenn eine Operation eine temporäre Tabelle benötigt, sich diese Tabelle in der MEMORY Engine befindet und DASS Zeichenfolgentypen immer in Fixes-Chunks gespeichert werden, so dass die großzügigen Definition kann dazu führen, dass die benötigte MEMORY-Temp-Tabelle auf die Festplatte
verschoben wird, anstatt
@RolandoMySQLDBA. Yep ... das auch ... Kollatierung wird auch hier ein Faktor (vor allem, wenn Sie UTF-8 verwenden und nicht-lateinische Zeichen haben) und das alles bringt Sie nur um, wenn Sie sich mit einer Memory Engine-Tabelle befassen, und führt zu einer schnelleren Reise auf die Festplatte
TechieGurl
5

Nach meinem Verständnis können die kleineren Felder direkt in den Index aufgenommen werden, während die längeren dies nicht können. Aufgrund dieser Einschränkung würde ich sagen, wenn Sie möchten, dass die Zeichenfolgen indexierbar sind, dass sie kürzer sind. Andernfalls funktioniert das Sortieren oder Vergleichen in der gleichen Zeit, unabhängig davon, ob die Felder 25 oder MAX sind.

jcolebrand
quelle
3

Stellen Sie sicher, dass Ihnen nicht der Raum ausgeht

Dieser Satz impliziert, dass Sie die Frage stellen, weil Sie nicht sicher sind, welche Daten Sie in der Datenbank speichern werden. Wenn dies zutrifft, sollten Sie dies so schnell wie möglich herausfinden, da Sie dies für die Kapazitätsplanung benötigen. Wenn Sie beispielsweise Datenelemente mit 7000 Zeichen erhalten, müssen Sie dies wissen, da dies Auswirkungen auf die Leistung eines DBMS haben würde.

Ich bevorzuge jedoch Spaltengrößen, die sich auf den erwarteten Inhalt beziehen. Es ist beispielsweise unwahrscheinlich, dass eine Telefonnummer länger als 50 Zeichen ist, selbst wenn Sie eine Landesvorwahl und eine Durchwahl angeben. Ebenso besteht eine Postleitzahl höchstwahrscheinlich aus 20 Zeichen oder weniger.

Larry Coleman
quelle