it-swarm.com.de

Welche Auswirkungen hat die Verwendung von CHAR vs VARCHAR auf die Leistung in einem Feld mit fester Größe?

Ich habe eine indizierte Spalte, in der ein MD5-Hash gespeichert ist. Daher speichert die Spalte immer einen 32-stelligen Wert. Aus irgendeinem Grund wurde dies eher als Varchar als als Char erstellt. Lohnt es sich, die Datenbank zu migrieren, um sie in ein Zeichen zu konvertieren? Dies ist in MySQL 5.0 mit InnoDB.

60
Jason Baker

Eine ähnliche Frage wurde bereits gestellt

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

Hier ist der Auszug meiner Antwort

Sie müssen die Kompromisse bei der Verwendung von CHAR gegen VARCHAR erkennen

Mit CHAR-Feldern weisen Sie genau das zu, was Sie erhalten. Beispielsweise weist CHAR (15) 15 Bytes zu und speichert sie, unabhängig davon, wie viele Zeichen Sie in das Feld einfügen. 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. Zum Beispiel weist VARCHAR (15) tatsächlich dynamisch bis zu 16 Bytes zu, bis zu 15 für Daten und mindestens 1 zusätzliches Byte, um die Länge der Daten zu speichern. Wenn Sie die Zeichenfolge 'Hallo' speichern müssen, die 6 Bytes und nicht 5 Bytes benötigt, muss die Zeichenfolgenmanipulation in jedem Fall eine Längenprüfung durchführen.

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 Offensichtlich hat VARCHAR 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 Indexsuchen 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 Anweisung zwingt alle VARCHARs, sich als CHARs zu verhalten. Ich habe dies bei meinem vorherigen Job im Jahr 2007 getan und eine 300-GB-Tabelle erstellt und die Indexsuche um 20% beschleunigt, ohne etwas anderes zu ändern. Es hat wie veröffentlicht funktioniert. Es wurde zwar ein Tisch mit fast doppelter Größe hergestellt, 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 durchlaufen und Spaltendefinitionen für jede Spalte basierend auf den darin enthaltenen Daten, den minimalen Feldwerten, den maximalen Feldwerten usw. empfohlen. Manchmal muss man bei der Planung von CHAR vs VARCHAR nur den gesunden Menschenverstand verwenden. 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 ANALYSE() für eine solche Spalte ausführen. Es kann sogar VARCHAR empfehlen. In diesem Fall wäre mein Geld immer noch für 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).

AKTUALISIEREN

Wenn es um MD5 geht, sollte die interne Berechnung von strlen beim Umschalten des gesamten Zeilenformats entfallen. Die Felddefinition muss nicht geändert werden.

Wenn der MD5-Schlüssel der einzige vorhandene VARCHAR ist , würde ich ihn verwenden und das Tabellenzeilenformat in fest konvertieren. Wenn eine signifikante Anzahl anderer VARCHAR-Felder vorhanden ist, würden sie ebenfalls davon profitieren. Im Gegenzug würde sich die Tabelle auf etwa das Doppelte ihrer Größe erweitern. Abfragen sollten jedoch ohne zusätzliche Optimierung um etwa 20% schneller werden.

57
RolandoMySQLDBA

Es sieht so aus, als würden Sie 1 Byte pro Wert oder etwa 3% sparen, wenn Sie in ein char konvertieren. Wahrscheinlich nicht wert, wenn Sie MD5 sowieso in hex speichern - Sie könnten 50% sparen, indem Sie stattdessen ein binary verwenden.

Vielen Dank an Ovais (siehe Kommentare) für den Hinweis, dass char(32)viel mehr als 32 Bytes verwenden kann, wenn Sie einen Multibyte-Zeichensatz verwenden.

Vielen Dank an Rick James für den Hinweis, dass Sie die Funktion unhex verwenden sollten, um die a-Hex-Zeichenfolge in eine Binärzeichenfolge umzuwandeln:

create table foo(bar varbinary(100));
insert into foo(bar) values(md5('a')); 
insert into foo(bar) values(unhex(md5('a'))); 
select length(bar) from foo;
 | Länge (Balken) | 
 | ----------: | 
 | 32 | 
 | 16 | 

db <> fiddle hier

Es lohnt sich meiner Meinung nach nicht zu ändern. Wenn Sie die Dokumentation hier durchsehen, sollte sie den Unterschied zwischen den beiden veranschaulichen. In Ihrem Nutzungsszenario bietet das eine keinen signifikanten Vorteil gegenüber dem anderen, es sei denn, Sie sind wirklich besorgt über den zusätzlichen Aufwand im Zusammenhang mit der 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 Ihren Zugriff nur, wenn der gesamte Datensatz eine feste Größe hat. Wenn Sie also ein Objekt variabler Größe verwenden, können Sie auch alle erstellen Variable Größe. Sie erhalten keine Geschwindigkeit, wenn Sie ein CHAR in einer Tabelle verwenden, die auch ein VARCHAR enthält. "

15
RThomas