Hi,
ich würde meine DB gerne optimieren. Ich nutze sha1 Datensätze als Primary Key. Die Zeichenlänge ist immer gleich, deswegen nutze ich CHAR(40) als Spaltentyp. Datenbanken sind bei fixen Zeilen- und Indexlängen deutlich performanter.
Als Zeichensatz hatte ich global UTF8 genutzt. Nach RFC 3629 ist spezifiziert, dass UTF8 ein bis vier Bytes je Zeichen belegt.
MySQL unterstützt drei Bytes, siehe dazu dev.mysql.com/doc/refman/5.0/en/charset-unicode.html.
Für mein CHAR(40) werden also 120 Bytes (40*3) reserviert.
Nun ärgere ich mich, dass meine Dateien immer größer und größer werden, dabei nutzt mein "Alphabet" gerademal 16 Zeichen von 128 möglichen (2^7) Alphabetzeichen, die sowieso reserviert sind.
Schritt 1 war erstmal mich von UTF8 zu verabschieden und aufs kleinere ASCII zu wechseln.
Dadurch ist der Datensatz in der Tat auf etwa ein drittel reduziert worden:
Leider habe ich festgestellt, dass der Index gleich blieb. Das der Index optimiert ist, liegt am Binary Tree wie er eben bei MyISAM und InnoDB immer genutzt wird.
Man sollte sich also eher freuen, dass utf8 die Sache nicht viel langsamer macht ;) Problem für mich, ist dass der Index irgendwann nicht mehr in den Arbeitspeicher passt.
Hierfür gibt es zwei Lösungen.
sha1 ist ein guter Hashing Algorithmus und damit schließen wir bei einer Index Länger von ~6 Zeichen schon ziemlich viele Datensätze aus, die wir uns vom Filesystem laden können.
Lösung "eins" wäre also ein partieller Index auf der sha1 Spalte. Nachteil am partiellen Index ist, dass wir mit der Festplatte (oder dem Festplattencache) in Kontakt kommen.
Für eine andere Optimierung habe ich nämlich "spalte 2" als Covering Index schon hinzugefügt, damit beide Spalten aus dem Arbeitsspeicher geladen werden.
Lösung "zwei" ist es die Daten stattdessen weiter zu komprimieren.
Man könnte den Zeichenraum also von 2^4 Hexzeichen also auf 2^7 ASCII Zeichen umzurechnen und die Zeichenlänge damit von 40 Byte auf xx Byte zu reduzieren.
Dafür würde man wieder CPU Zeit verschwenden. Haltet ihr das für eine gute Lösung? Ich muss mal ausrechnen wieviel Platz ich tatsächlich sparen würde.
ich würde meine DB gerne optimieren. Ich nutze sha1 Datensätze als Primary Key. Die Zeichenlänge ist immer gleich, deswegen nutze ich CHAR(40) als Spaltentyp. Datenbanken sind bei fixen Zeilen- und Indexlängen deutlich performanter.
Als Zeichensatz hatte ich global UTF8 genutzt. Nach RFC 3629 ist spezifiziert, dass UTF8 ein bis vier Bytes je Zeichen belegt.
MySQL unterstützt drei Bytes, siehe dazu dev.mysql.com/doc/refman/5.0/en/charset-unicode.html.
Für mein CHAR(40) werden also 120 Bytes (40*3) reserviert.
Nun ärgere ich mich, dass meine Dateien immer größer und größer werden, dabei nutzt mein "Alphabet" gerademal 16 Zeichen von 128 möglichen (2^7) Alphabetzeichen, die sowieso reserviert sind.
Schritt 1 war erstmal mich von UTF8 zu verabschieden und aufs kleinere ASCII zu wechseln.
Dadurch ist der Datensatz in der Tat auf etwa ein drittel reduziert worden:
Leider habe ich festgestellt, dass der Index gleich blieb. Das der Index optimiert ist, liegt am Binary Tree wie er eben bei MyISAM und InnoDB immer genutzt wird.
Man sollte sich also eher freuen, dass utf8 die Sache nicht viel langsamer macht ;) Problem für mich, ist dass der Index irgendwann nicht mehr in den Arbeitspeicher passt.
Hierfür gibt es zwei Lösungen.
sha1 ist ein guter Hashing Algorithmus und damit schließen wir bei einer Index Länger von ~6 Zeichen schon ziemlich viele Datensätze aus, die wir uns vom Filesystem laden können.
Lösung "eins" wäre also ein partieller Index auf der sha1 Spalte. Nachteil am partiellen Index ist, dass wir mit der Festplatte (oder dem Festplattencache) in Kontakt kommen.
Für eine andere Optimierung habe ich nämlich "spalte 2" als Covering Index schon hinzugefügt, damit beide Spalten aus dem Arbeitsspeicher geladen werden.
Lösung "zwei" ist es die Daten stattdessen weiter zu komprimieren.
Man könnte den Zeichenraum also von 2^4 Hexzeichen also auf 2^7 ASCII Zeichen umzurechnen und die Zeichenlänge damit von 40 Byte auf xx Byte zu reduzieren.
Dafür würde man wieder CPU Zeit verschwenden. Haltet ihr das für eine gute Lösung? Ich muss mal ausrechnen wieviel Platz ich tatsächlich sparen würde.