Ich habe eine indizierte Spalte, die einen MD5-Hash speichert. Daher speichert die Spalte immer einen 32-stelligen Wert. Aus welchem Grund auch immer wurde dies eher als ein Varchar als ein Char erstellt. Lohnt es sich, die Datenbank zu migrieren, um sie in ein Zeichen zu konvertieren? Dies ist in MySQL 5.0 mit InnoDB.
mysql
performance
innodb
varchar
Jason Baker
quelle
quelle
Antworten:
Eine ähnliche Frage wurde zuvor gestellt
Auswirkungen auf die Leistung von MySQL VARCHAR-Größen
Hier ist der Auszug meiner Antwort
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
TRADEOFF # 1 VARCHAR hat natürlich den Vorteil, dass Daten mit variabler Länge kleinere Zeilen und damit kleinere physische Dateien erzeugen würden.
TRADEOFF # 2 Da CHAR-Felder aufgrund fester Feldbreiten weniger Zeichenfolgenmanipulation 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:
Diese Direktive zwingt alle 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:
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
CHAR(15)
weiterspringen, da sich die Länge der IP-Adressen nicht allzu sehr ändert und die zusätzliche Komplexität der String-Manipulation durch ein zusätzliches Byte gesteuert wird. Sie könnten immer nochPROCEDURE ANALYSE()
gegen eine solche Kolumne vorgehen. 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 Macht geht große Verantwortung einher (Klischee aber wahr).
AKTUALISIEREN
Bei MD5 sollte die
strlen
interne Berechnung entfallen, wenn das gesamte Zeilenformat umgeschaltet wird. Die Felddefinition müsste nicht geändert werden.Wenn der MD5-Schlüssel das einzige vorhandene VARCHAR ist, würde ich das Tabellenzeilenformat in ein festes Format konvertieren . Wenn eine signifikante Anzahl anderer VARCHAR-Felder vorhanden ist, würden diese ebenfalls davon profitieren. Im Gegenzug würde sich der Tisch auf etwa die doppelte Größe vergrößern. Abfragen sollten jedoch ohne zusätzliche Optimierung um etwa 20% beschleunigt werden.
quelle
bit
undbinary
?Es sieht so aus, als würden Sie 1 Byte pro Wert einsparen oder etwa 3%, wenn Sie in a konvertieren
char
. Es lohnt sich wahrscheinlich nicht, wenn Sie MD5 ohnehin hexadezimal speichern - Sie könnten 50% sparen, wenn Siebinary
stattdessen a verwenden.Vielen Dank an Ovais (siehe Kommentare) für den Hinweis, dass
char(32)
bei Verwendung eines Multibyte-Zeichensatzes viel mehr als 32 Byte verwendet werden können.Vielen Dank an Rick James, der darauf hingewiesen hat, dass Sie die
unhex
Funktion verwenden sollten, um eine Hex-Zeichenfolge in eine binäre Zeichenfolge umzuwandeln:db <> hier fummeln
quelle
binary
- oder habe ich das falsch verstanden?BINARY
macht nur sehr wenig, wenn Sie es auch verwendenUNHEX()
. Das heißt, Sie könnenUNHEX(MD5(x))
in einem 16-Byte-BINARY(16)
Speicher speichern , um gegenüber dem SpeichernMD5(x)
in einen erheblichen Speicherplatz einzusparenCHAR(32) CHARACTER SET ascii
.Es lohnt sich meiner Meinung nach nicht zu ändern. Wenn Sie die Dokumentation hier durchsehen, sollte dies den Unterschied zwischen den beiden veranschaulichen. In Ihrem Nutzungsszenario bietet das eine keinen nennenswerten Vorteil gegenüber dem anderen, es sei denn, Sie sind wirklich besorgt über den zusätzlichen Overhead in Bezug auf die Zeilengröße.
http://dev.mysql.com/doc/refman/5.0/en/char.html
Beachten Sie auch den ersten Kommentar zu der Dokumentation, auf die ich oben verweise ... "CHAR beschleunigt den Zugriff nur, wenn der gesamte Datensatz eine feste Größe hat. Wenn Sie also ein Objekt mit variabler Größe verwenden, können Sie auch alle erstellen Variable Größe. Sie gewinnen keine Geschwindigkeit, wenn Sie ein CHAR in einer Tabelle verwenden, die auch ein VARCHAR enthält. "
quelle