SQL Feld Typen und Performance

Domi83

Rear Admiral
Registriert
Feb. 2010
Beiträge
5.462
Moin Leute... :)
Ich habe da mal eine Performance technische Frage bezüglich MySQL (PHP wäre auch noch eine Frage!) :D

Und zwar geht es um die Feldtypen (int, varchar, float, date)... diese verwende ich in einer Tabelle meiner Datenbank. Ich habe Felder wie Bankleitzahl oder Kontonummer die ich als int, aber auch als varchar deklarieren könnte. Klar macht ein int wohl mehr Sinn, weil es nur zahlen sind. Aber macht es Performance technisch einen großen Unterschied, ob ich nun daraus "varchar" oder "int" mache?

Bezüglich Performance meine ich die Abfrage, wenn ich jetzt ein SELECT mache, und ich meine auch ein wenig den Verbrauch des Speichers... "benötigt ein varchar(10) Feld mehr Speicher als ein int(10)?"

Die Felder mit einem Datum (0000-00-00) werde ich "DATE" lassen, und die Zeitstempel lasse ich "DATETIME", lassen... aber ob ich bei dem einen oder anderen Feld varchar oder int nehme, ist für mich noch unsicher. Berechnet werden soll mit den Feldern nichts, Ausnahme die "float" Felder :D

Was für mich zusätzlich auch noch interessant wäre, Felder mit NULL oder default wert und deren Speicherbelegung. Das Projekt was wir hier in der Firma planen, wird zu Anfang erst einmal nur ein Testlauf sein und könnte nach einem Jahr wieder eingestellt werden. Aber für den Fall, dass es bestehen bleibt, möchte ich das schon mal ordentlich haben :)

Gruß, Domi

p.s. Und was PHP angeht, interessiert mich mal ob eine 100KB große Datei genauso lange laden würde (beim Client) wie eine 100KB große Ausgabedatei (HTML)... Ich frage das, weiß ich immer versuche meine PHP Dateien klein zu halten. Ich bin zwar noch nie bei 100KB gewesen, aber 22KB hab ich ab und an mal :D
 
Zahlen (zum Rechnen) sind int/float plus Äquivalente, alles andere (var)char. Als was würdest du eine Postleitzahl speichern, mal so als Fangfrage?
 
Für ein varchar(10) in UTF8 wird in einer MyISAM-Zeile mit 31 Byte reserviert. Ein Int(1) mit 4 Byte.

Siehe auch: http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

Edit: Die größe der PHP-Datei ist eigentlich irrelevant. Achte darauf nicht. Die CPUs sind heute zum Glück so schnell, dass du dir bei kleinen Anwendungen keine Gedanken um Performance machen musst. Wichtig ist, dass du auf Datenbankseite keine Scheisse baust und die Daten vernünftig speicherst. Denn schon bei 30-40k Zeilen, kann dich das in ein paar Jahren extrem ärgern ;) *an meinen den ersten Shop denk*
 
Zuletzt bearbeitet:
Moin.. Schon mal meinen Dank für Eure Anteilnahme :)
Yuuri schrieb:
Als was würdest du eine Postleitzahl speichern, mal so als Fangfrage?
Also meine ersten Ansätze (vor drei Jahren) liefen darauf hinaus, dass ich sie immer als "INT(5)" deklariert hatte. Problematik war dann die führende "0", also habe ich es als VARCHAR(5) eingetragen, da ich damit nicht rechnen werde und eine führende "0" eintragen kann :)

Enigma schrieb:
Für ein varchar(10) in UTF8 wird in einer MyISAM-Zeile mit 31 Byte reserviert. Ein Int(1) mit 4 Byte.
Okay, VARCHAR(10) hat 31Byte, somit wäre der INT(10) dann bei 40Byte, richtig?

Meine Tabellen haben "CHARACTER SET utf8 COLLATE utf8_general_ci" und verwenden auch die MyISAM Engine. Mit den anderen hatte ich mich nie befasst... ist auch das erste mal, dass ich mich damit befasse. Hatte vorher zwar noch keine Probleme, aber falls dieses Projekt ein etwas größeres wird, möchte ich das nicht bereuen :)

Gruß, Domi
 
Domi83 schrieb:
Moin.. Schon mal meinen Dank für Eure Anteilnahme :)

Also meine ersten Ansätze (vor drei Jahren) liefen darauf hinaus, dass ich sie immer als "INT(5)" deklariert hatte. Problematik war dann die führende "0", also habe ich es als VARCHAR(5) eingetragen, da ich damit nicht rechnen werde und eine führende "0" eintragen kann :)

So mache ich es auch ;)

Könnte man eigentlich auch INT(5) unsigned zerofill für die PLZ nehmen ?
 
Domi83 schrieb:
Also meine ersten Ansätze (vor drei Jahren) liefen darauf hinaus, dass ich sie immer als "INT(5)" deklariert hatte. Problematik war dann die führende "0", also habe ich es als VARCHAR(5) eingetragen, da ich damit nicht rechnen werde und eine führende "0" eintragen kann :)
Gut dann kennst du den ja schon. Im Fall der Fälle kann sowas ja auch bei Bankverbindungen auftreten (rate ich gerade nur), also lieber varchar nehmen. Da wo du nie sicher gehen kannst, dass Zahlen eben bspw. führende Nullen besitzen könnten, solltest du lieber die Zahlen als Text speichern. int/float würde ich wie gesagt nur nehmen, für eindeutig numerische Werte (Anzahl, Geldbetrag, IDs, ...). Die Hausnummer bspw. ist ja auch nicht immer numerisch. Weitere Beispiele fallen mir grad nicht mehr ein. :D
 
vilden schrieb:
Könnte man eigentlich auch INT(5) unsigned zerofill für die PLZ nehmen ?
Könntest Du, aber hier in DE gibt es PLZ die mit 0 anfangen, die führende 0 wird dann nicht mit gespeichert. Somit würde dann bei der PLZ "04123" nur "4123" in der Datenbank stehen. Um die Ausgabe wieder anzupassen, müsstest Du dann str_pad() verwenden. Darum wäre die Verwendung von VARCHAR(5) sinnvoller ;)

Yuuri schrieb:
int/float würde ich wie gesagt nur nehmen, für eindeutig numerische Werte (Anzahl, Geldbetrag, IDs, ...).
Gut, dass mit den Geldbeträgen habe ich schon so erledigt. Die Felder wo ich weiß, dass es ein Datum ist, haben "DATE" oder "DATETIME", PLZ und Anschrift haben mittlerweile einen VARCHAR und Kontonummer + BLZ haben jetzt auch VARCHAR bekommen.

Macht es denn mehr Sinn, einen "default" Wert in ein leeres Feld einzutragen, oder ist NULL sinnvoller? Ich glaube für eine Überprüfung, könnte man bei NULL mit isset() arbeiten, aber ist NULL = 0Byte?
 
Domi83 schrieb:
Könntest Du, aber hier in DE gibt es PLZ die mit 0 anfangen, die führende 0 wird dann nicht mit gespeichert. Somit würde dann bei der PLZ "04123" nur "4123" in der Datenbank stehen. Um die Ausgabe wieder anzupassen, müsstest Du dann str_pad() verwenden. Darum wäre die Verwendung von VARCHAR(5) sinnvoller ;)

Benutze auch VARCHAR ;)
Habe mal Filemaker Pro als "Frontend" genutzt und da ist es egal ob ich da nun INT(5) Zerofill verwende, er zeigt mir die 0 auch ohne weiteres an. Ist sicher nicht überall so wenn du es so schreibst ;)
 
Domi83 schrieb:
Okay, VARCHAR(10) hat 31Byte, somit wäre der INT(10) dann bei 40Byte, richtig?
ein Int braucht 4 Byte.


Aber die Größe der Datentypen spielt für die Performance eine untegeordnete Rolle, designe die Datenbank lieber sinnvoll und auch mit sinnvollem Einsatz von Indexen.
Es gilt weiterhin: Premature optimization is rhe root of all evil.
Bau die Datenbank nach bestem Wissen und Gewissen und nicht nach dem was du denkst, was performant sein könnte.
 
Ach so, ich dachte das bezog sich nur auf INT(1) mit den 4 Byte und wenn ich halt INT(2) habe, wären es 8 Byte. Dann vermute ich mal, dass ein VARCHAR(x) auch immer 31 Byte benötigen wird, richtig?

Im Prinzip ist meine Datenbank fertig. Habe FLOAT Werte für die Preise genommen, INT für die ID, Geburtstage sind DATE, und der Rest ist VARCHAR. Ich habe noch gesagt, dass die Felder auch "NULL" sein können, wenn nichts drin ist.

Was die Indexes angeht, da hatte ich mich wegen dem Fremdschlüssel und CASCADE belesen, man könnte den so einstellen das beim löschen in der Haupttabelle auch in der Unter-Tabelle die Zeilen mit dem Wert X gelöscht werden. Aber das funktioniert irgendwie nicht :D

Gruß, Domi
 
Domi83 schrieb:
Ach so, ich dachte das bezog sich nur auf INT(1) mit den 4 Byte und wenn ich halt INT(2) habe, wären es 8 Byte.
Alle Datentypen brauchen konstanten Speicher, bis auf varchar und char, da richtet es sich nach der Größenangabe.
Bei Int ist das das x in Int(x) nur eine Info für das MySQL-Kommandozeilenprogramm, dass es nur x Ziffern der Zahl anzeigen soll.


Domi83 schrieb:
Dann vermute ich mal, dass ein VARCHAR(x) auch immer 31 Byte benötigen wird, richtig?
falsch!
varchar(x) benötigt bei UTF-8 3*x+1 Byte, char nur 3*x Byte.


Domi83 schrieb:
Im Prinzip ist meine Datenbank fertig. Habe FLOAT Werte für die Preise genommen
schlechte Idee! Die Abbildung von Fließkommazahlen ist nicht genau, nimm bitte DECIMAL.


Domi83 schrieb:
Was die Indexes angeht, da hatte ich mich wegen dem Fremdschlüssel und CASCADE belesen, man könnte den so einstellen das beim löschen in der Haupttabelle auch in der Unter-Tabelle die Zeilen mit dem Wert X gelöscht werden. Aber das funktioniert irgendwie nicht :D
Fremdschlüssel und Schlüssel zur Performancesteierung sind wieder 2 paar Schuhe.


Ich hoffe du verstehst nun, warum ich meine, dass du von der Optimierung Abstand nehmen sollst, du weisst scheinbar (ist ja nicht schlimm) so wenig über MySQL, dass du einfach nicht die richtigen Entscheidungen treffen kannst. Du entscheidest einfach aus dem Bauch heraus, was dir sinnvoll performant erscheint. Selbst wenn das DB-Layout nachher performant sein sollte, kannst du durch schlechte Querys wieder alles kaputt machen, man optimiert nur, wenn man soetwas Ahnung hat.
 
ice-breaker schrieb:
Fremdschlüssel und Schlüssel zur Performancesteierung sind wieder 2 paar Schuhe.
Okay, dass hätte ich nicht ineinander werfen sollen.. das mit den Fremdschlüsseln sollte keine Performance-Geschichte sein ;)

ice-breaker schrieb:
varchar(x) benötigt bei UTF-8 3*x+1 Byte, char nur 3*x Byte.
Okay, dann weiß ich darüber auch schon mal ein Bisschen besser bescheid.. das ist ja dann nur eine simple Rechnung. Ich ging jetzt fast davon aus, wenn int(x) immer 4Byte benötigt, braucht varchar(x) auch immer 31Byte, aber dann erklärt sich das ja schon mal.

ice-breaker schrieb:
schlechte Idee! Die Abbildung von Fließkommazahlen ist nicht genau, nimm bitte DECIMAL.
Okay, dann ist das auch geklärt. In meiner ersten Variante hatte ich nämlich "praemie DECIMAL(4,5) unsigned NULL" gemacht, dann werde ich das auch wieder verwenden.

ice-breaker schrieb:
Ich hoffe du verstehst nun, warum ich meine, dass du von der Optimierung Abstand nehmen sollst, du weisst scheinbar (ist ja nicht schlimm) so wenig über MySQL
Joa, dass stimmt wohl.. In der Ausbildung haben wir nie direkt über das eine oder andere Szenario gesprochen. Datenbanken aufbauen, SELECT, UPDATE, DELETE, JOIN oder solche Spielchen bekommen ich hin, aber das kleine drumherum habe ich sonst nie hinterfragt.

Ich habe zwar das eine oder andere Manual gelesen, aber auch nur gedacht "hää?" und wenn man dann einmal nachfragt was das eigentlich genau macht, kommt auch nur "lies die Anleitung" da kann ich dann auch nur "danke!" sagen :)

Gruß, Domi
 
Zurück
Oben