Die Wahl des richtigen Feldtypes ist sehr wichtig bei Relationalen Datenbanken, da mit ihm der zur Verfügung stehende Zeichensatz und Länge definiert wird. Außerdem wird durch ihn die Speichergröße des Feldes und damit die Speichergröße der Zeile bestimmt. Deshalb soll man immer den kleinst möglichen Feldtype wählen der für seine Bedürfnisse ausreicht. Will man nun ein Datum speichern, gibt es mehrere Möglichkeiten dies zu tun.
Soll es ein Datum mit Uhrzeit sein bietet sich MySQL TIMESTAMP (4 Byte), DATETIME (8 Byte) und INT (4 Byte) an. Braucht man nur ein Datum, dann reicht auch DATE aus. DATETIME fällt sofort raus, da es zu viel Speicherplatz belegt. Der MySQL TIMESTAMP ist in der Speicherung und Darstellung nicht das gleiche wie ein UNIX Timestamp und da ich viel mit UNIX Timestamps arbeite, würde dies ein dauerndes umrechnen bedeuten. Bisher habe ich mich immer für INT entschieden wenn es nicht gerade um Geburtstage oder ähnliches geht die außerhalb des UNIX Timstamps liegen können, da MySQL mit Zahlen sehr gut umgehen kann und ich diese deshalb immer bevorzuge wenn möglich. Außerdem kann man damit ja Datum und Uhrzeit benutzen, was DATE nicht kann und es kostet nur 1 Byte mehr…
Um genau dieses 1 Byte geht es nun aber, den wenn man erst mal Tabellen mit mehreren Millionen Einträgen hat, zählt jedes Byte! Will man diese Spalte auch noch mit einem Index belegen, schlägt es sogar doppelt zu Buche und verbraucht nebenbei auch noch Platz im Memory (key_buffer zum Beispiel). Außerdem erhöht die größere Möglichkeit an Werten auch die Kardinalität des Index, was bei Sortierungen und Joins relevant wird.
Hier ein real life Beispiel:
Die Tabelle hat nur 2 Werte. Eine id als UNSIGNED INT und PRIMARY KEY, sowie ein Datum aktuell als INT auf dem ein Index liegt. Die Uhrzeit brauche ich aber eigentlich gar nicht. Die Tabelle hatte zum Zeitpunkt des Tests knappe 20 Millionen Zeilen (mittlerweile sind es 30 Millionen und es sind 60-120 Millionen angepeilt) und diese Stats:
Type Usage Data 189.3 MiB Index 446.5 MiB Total 635.9 MiB
Für diesen Test habe ich die Tabellen Struktur kopiert und das INT Feld durch ein DATE Feld ersetzt. Dann noch die Daten kopieren und vergleichen.
INSERT INTO
testdate
(id, date)
SELECT
source.id,
FROM_UNIXTIME(source.timeint, '%Y-%m-%d') AS date
FROM testint AS source
ON DUPLICATE KEY UPDATE
date = FROM_UNIXTIME(source.timeint, '%Y-%m-%d');
Type Usage Data 168.3 MiB Index 420.9 MiB Total 589.2 MiB
Man kann also schon mal eine Speicherersparnis von 47 MB erkennen. Da ich in dieser Anwendung aktuell 12 dieser Tabellen habe, wären dies schon 564MB Ersparnis.
Fazit
Man sollte sich immer genau vor Auge führen was man speichern möchte, wofür man es braucht und danach das richtige Feld wählen. Auch die Ersparnis von nur 1 Byte kann sich auszahlen! Wenn man also nur ein Datum braucht, dann sollte man auch DATE wählen.
No related posts.