SQL Datenbank Speicherplatz sparen?

deintag85

Erfahrenes Mitglied
Hallo,
ich betreibe einen CounterService, der für jeden Counter folgende Tabelle erstellt :

Code:
$sql="CREATE TABLE IF NOT EXISTS `$counter` (
	  `IP` text NOT NULL,
	  `Datum` datetime NOT NULL,
	  `OS` varchar(50) NOT NULL,
	  `Browser` varchar(50) NOT NULL,
	  `Screen` varchar(25) NOT NULL,
	  `Depth` int(10) NOT NULL,
	  `Location` varchar(50) NOT NULL,
	  `Referer` varchar(255) NOT NULL,
	  `Keyword` varchar(255) NOT NULL,
	  `Java` varchar(10) NOT NULL,
	  `Cookie` varchar(10) NOT NULL
	) ENGINE=MyISAM DEFAULT CHARSET=latin1";

Jeder Zugriff auf einer Seite führt zu einem Eintrag in der Datenbank, sodass ich sehen kann wieviele verschiedene Besucher online waren und zu welcher Uhrzeit sie die Website aufgerufen haben.

Nun denn. Ich habe gerade eine Testphase und habe einen Benutzer der mir ca. 20.000 Einträge pro Tag macht. Das entspricht ca. 2 MB pro Tag an Speicherplatzverbrauch für seine Tabelle.

Wenn ich mir ausrechne, was wäre wenn ich 1000 Counter betreiben würde, das wären 2GB pro Tag / 62 GB pro Monat Speicherplatz. Dann wäre mein Server schneller voll als man denkt.

Nun. Welche Möglichkeiten gibt es um die Speicherplatzmenge möglichst gering zu halten? Ich habe etwas gelesen über "Tabellenkompression". Wie genau funktioniert das? Ist das denn angebracht für so etwas? Welche Alternativen gibt es? Gibt es eine?

Soll ich vielleicht die Datentypen meiner Tabellenfelder nochmal überdenken auf Speicherärmere Typen?

Lieben Gruß
 
Moin,

Soll ich vielleicht die Datentypen meiner Tabellenfelder nochmal überdenken auf Speicherärmere Typen?

Naja, du hast da einen Haufen varchars-diese alleine machen ca. 700 Bytes aus.

Ich würde erstmal versuchen, die Sache zu normalisieren.

Location,OS,Browser,Screen,depth,Keyword,JAVA und Cookie schreien geradezu danach(falls sich dahinter das verbirgt, was ich denke).

Dann Referer.....falls es dort ausreichen würde, nur externe Referers zu zählen, bietet das auch Sparpotential.

Denkbar wäre auch, die varchar-Felder in text umzuwandeln, und die Werte vorher mit PHP auf die vorgesehene Länge zu stutzen.

Und last but not least:
Irgendwann (täglich,monatlich, etc.)solltest du die Datensätze in passender Form archivieren, also in einer Zusammenfassung abspeichern, und aus der Tabelle entfernen...tust du das nicht, fliegt dir die Sache früher oder später eh um die Ohren :)
 
Moin,



Naja, du hast da einen Haufen varchars-diese alleine machen ca. 700 Bytes aus.


Denkbar wäre auch, die varchar-Felder in text umzuwandeln, und die Werte vorher mit PHP auf die vorgesehene Länge zu stutzen.

Hallo,

Nun, varchar heissen deswegen varchar, weil es Textfelder variabler Länge sind, es wird also nur der Platz benötigt, welcher der String effektiv beanspricht plus 1 oder Byte für interne Zwecke (Im gegensatz zu Char, dort wird mit Blanks aufgefüllt bis zur deklarierten Länge

(Kann natürlich je nach DB varieren....)



gruss
 
Moin deintag85,

Du könntest - je nach Anteil Deiner Stammkunden auf Deiner Site- das Datenvolumen um 50-95% eindampfen, wenn Du nicht für jeden Anlauf eines Benutzers (vom immer gleich bleibenden Rechner aus) einen neuen Datensatz anlegen würdest.
Wenn User "Heinz" am heutigen Datum 29x auf Deiner Site vorbeischaut, dann hat er doch 29 Datensätze in Deiner Tabelle - mit Einträgen, die bis auf die Uhrzeit identisch sind.
Okay, vielleicht wird nicht jeder Benutzer immer die gleiche IP den ganzen Tag lang bzw. Monat für Monat benutzen, aber geben soll es solche User.

Da nun außerdem das Ganze nicht Usernamen-bezogen ist (bzw. von einer etwaigen Anmeldung abhängt), ob Du den Satz nun speicherst---> dann reicht es doch für jede noch so abgedrehte Statistikauswertung, wenn Du meinetwegen alle IPs mit "OS=Windows" und Location="South Africa" in EINEM Datensatz subsummierst mit einem Feld "ANZAHL", dass jeweils bei einem neuen Hit um 1 hochgezählt wird.

Oder aber- Ein Feld "AnzahlDiesenMonat", welches Du jeweils am Monatsletzten um 23:59 automatisch umbuchst in ein Feld "AnzahlGesamt" und auf 0 setzt .. etc pp.

Und nichts gegen "Normalisieren einer Tabelle"... ist ja auch durchaus richtig.
Aber ein Schritt kommt doch noch vorher: erstmal die Überlegung, welche "Daten" müssen/sollten denn überhaupt gesammelt werden, weil sie gleichzeitig auch "Informationen" sind oder gar "erhaltenswerte Informationen"?

Wenn eine Seitenzählertabelle "62 GByte pro Monat" brauchen könnte.... ja hey... dann würde ich ich erstmal die Finger von der Tastatur nehmen und einen kleinen Spaziergang machen.... mal einen anderen Blick bekommen.

Kann ja nicht sein, dass da pro Monat mehr zusammengeharkt wird, als auf einer 10-Jahres-Ausgabe "Telefonnummern-Deutschland".steht oder mehr als der Stoiber über uns sammelt.

Grüße
Biber
 
Zuletzt bearbeitet:
Moin deintag85,

Du könntest - je nach Anteil Deiner Stammkunden auf Deiner Site- das Datenvolumen um 50-95% eindampfen, wenn Du nicht für jeden Anlauf eines Benutzers (vom immer gleich bleibenden Rechner aus) einen neuen Datensatz anlegen würdest.
Wenn User "Heinz" am heutigen Datum 29x auf Deiner Site vorbeischaut, dann hat er doch 29 Datensätze in Deiner Tabelle - mit Einträgen, die bis auf die Uhrzeit identisch sind.
Okay, vielleicht wird nicht jeder Benutzer immer die gleiche IP den ganzen Tag lang bzw. Monat für Monat benutzen, aber geben soll es solche User.

Da nun außerdem das Ganze nicht Usernamen-bezogen ist (bzw. von einer etwaigen Anmeldung abhängt), ob Du den Satz nun speicherst---> dann reicht es doch für jede noch so abgedrehte Statistikauswertung, wenn Du meinetwegen alle IPs mit "OS=Windows" und Location="South Africa" in EINEM Datensatz subsummierst mit einem Feld "ANZAHL", dass jeweils bei einem neuen Hit um 1 hochgezählt wird.

Oder aber- Ein Feld "AnzahlDiesenMonat", welches Du jeweils am Monatsletzten um 23:59 automatisch umbuchst in ein Feld "AnzahlGesamt" und auf 0 setzt .. etc pp.

Und nichts gegen "Normalisieren einer Tabelle"... ist ja auch durchaus richtig.
Aber ein Schritt kommt doch noch vorher: erstmal die Überlegung, welche "Daten" müssen/sollten denn überhaupt gesammelt werden, weil sie gleichzeitig auch "Informationen" sind oder gar "erhaltenswerte Informationen"?

Wenn eine Seitenzählertabelle "62 GByte pro Monat" brauchen könnte.... ja hey... dann würde ich ich erstmal die Finger von der Tastatur nehmen und einen kleinen Spaziergang machen.... mal einen anderen Blick bekommen.

Kann ja nicht sein, dass da pro Monat mehr zusammengeharkt wird, als auf einer 10-Jahres-Ausgabe "Telefonnummern-Deutschland".steht oder mehr als der Stoiber über uns sammelt.

Grüße
Biber

Hallo!
Ich bin wieder hier ;-) Ich glaube du könntest Recht haben mit dem was du sagst. Ich habe einen Counter der nun etwa 400.000 Datenbankeinträge produziert hat. Die Abfrage dauert (warum auch immer) ca. 40-60 Sekunden. Das ist unmenschlich und unzumutbar für meine Besucher.

Ich werde wohl das Konzept überdenken, dass ich nicht jedesmal einen neuen Eintrag mache sondern für Seitenaufrufe einfach ein weiteres Feld mache.

Aber dennoch wird sicherlich das Problem wieder kommen, dass ich soviele Einträge habe, dass eine Abfrage zu lange dauert. Was mache ich bei meiner Abfrage falsch? Ich frage ja nur COUNT(DISTINCT IP) VON DEM TAG X ab.

Wie kann man denn die Abfrage beschleunigen?
LG
 
Hallo!

Aber dennoch wird sicherlich das Problem wieder kommen, dass ich soviele Einträge habe, dass eine Abfrage zu lange dauert. Was mache ich bei meiner Abfrage falsch? Ich frage ja nur COUNT(DISTINCT IP) VON DEM TAG X ab.

Wie kann man denn die Abfrage beschleunigen?
LG

Hallo,

- Erstmal, welches DBMS verwendest du denn ? Sind Indizies gesetzt und korrekt ? Aufgrund deines Beispiel SQL wäre sicher auf IP und dem Datumsfeld ein Index notwendig.
- Sind die Statistiken aktuell resp. überhaupt vorhanden ?
- 400000 Datensätze sind "nicht viel", dies solle in der Regel sehr performant sein
- Wenn deine DB dies unterstützt, könntest du die Tabelle auch Range-partitionieren, z.b. Monatspartitionen


Gruss
 
Hallo,

- Erstmal, welches DBMS verwendest du denn ? Sind Indizies gesetzt und korrekt ? Aufgrund deines Beispiel SQL wäre sicher auf IP und dem Datumsfeld ein Index notwendig.
- Sind die Statistiken aktuell resp. überhaupt vorhanden ?
- 400000 Datensätze sind "nicht viel", dies solle in der Regel sehr performant sein
- Wenn deine DB dies unterstützt, könntest du die Tabelle auch Range-partitionieren, z.b. Monatspartitionen


Gruss

Das war jetzt zu hoch für mich, glaube ich. Also ich nutze mySQL in verbindung mit php. Ich habe keine Ahnung was Indizes sind. Was heisst "resp."?

LG
 
Das war jetzt zu hoch für mich, glaube ich. Also ich nutze mySQL in verbindung mit php. Ich habe keine Ahnung was Indizes sind. Was heisst "resp."?

LG

Hallo..

Ich habe keine Ahnung was Indizes sind

Dann hast du schlechte Karten...Ich würde mich zuest mal schlau machen :

Indizies :

http://dev.mysql.com/doc/refman/5.1/en/optimizing-database-structure.html

Partitionierung :
http://dev.mysql.com/doc/refman/5.1/en/partitioning.html

...und vielleicht mal die Doku heranziehen

In deinem Fall würden 2 Indizies notwendig sein :

CREATE INDEX ip_idx ON mytable (IP);

CREATE INDEX Datumsfeld_idx ON mytable (Datumsfeld);



gruss
 
Zuletzt bearbeitet:
Moin,

jetzt schalte ich mich auch mal ein.

Also ich hab mehrere MySQl´s am laufen die Datenmengen von > 60GB handeln. Die größte DB ist ein 6 Maschinen MySQL-Cluster auf 2,4 TB "Nutzdaten" (ohne Indexes, HEAP´s u. VIEWS; mit > 3TB).
Und selbst bei solchen Datenmengen sind die Abfragen rasent schnell. Also das Argument, die Datenmenge wird zu hoch ist eher kritisch zu betrachten.

Allerdings sind um solche Datenmengen zu handeln die Standardeinstellungen von MySQL eher suboptimal. Auch empfiehlt es sich im MySQL selber bzw. den DBMS-Engines schon beim kompilieren einige neue Einstellungen mitzugeben.

z.B. gibts bei InnoDB eine Einstellung (my.ini) in welcher du die Engine zwings für jede Tabelle eine eigene File zu erstellen oder eine RIESIGE File für alles was InnoDB ist... Leider ist letzteres Standard und ein absoluter Performance Killer.

Weiterhin wichtig sind diverse Finetunings an den Hostmaschinen selber (unter Linux z.B. READ AHEAD Einstellungen)

Auch die richtige Hardware will für sowas gewählt sein. Wir setzen ausschließlich auf RAID 10 Systeme mit 2,5`` SAS Scheiben (147GB bei 10k U/min).

Im Grunde bringt aber die beste Maschine u. DB effektiv NICHTS! wenn das Modell nix taugt.
Dies bezüglich haben ja dir ja schon einige erschöpfende Informationen gegeben. Im Zweifelsfall die Doku von MySQL ist zwar neuerdings etwas "häßlich" zu lesen aber tu dir das mal an, dann wird sich vieles von selbst klären.

An irgendwelche "Speichergrenzen" wirst du wohl solange der Plattenplatz reicht nicht stoßen..
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück