[PHP/MySQL] Daten effizient verarbeiten

theHacker

sieht vor lauter Ads den Content nicht mehr
Teammitglied
ID: 69505
L
20 April 2006
22.682
1.316
Moin.

Ich habe eine Tabelle mit Daten, vereinfacht einmal INT mit Unix-Timestamp und einem INT für mein Datum, was ich haben will. Daten sind mehrmals täglich vorhanden.

Mein Ziel ist es jetzt, eine Tabelle mit dem jeweils ersten Datum eines jeden Tages herauszulesen.

Mein erster Versuch ist es, alles in der DB zu machen:
Code:
[FONT=Courier New][B][COLOR=#9932cc]SELECT[/COLOR][/B] time, data
[B][COLOR=#9932cc]FROM[/COLOR][/B] [COLOR=Black][B]table[/B][/COLOR]
[B][COLOR=#9932cc]WHERE[/COLOR][/B] time [B][COLOR=#9932cc]IN[/COLOR][/B] [/FONT][FONT=Courier New][COLOR=#9932cc]([/COLOR]
  [/FONT][FONT=Courier New][B][COLOR=#9932cc]SELECT[/COLOR][/B] [B][COLOR=#9932cc]MIN[/COLOR][/B][COLOR=#9932cc]([/COLOR]time[COLOR=#9932cc])[/COLOR] [B][COLOR=#9932cc]AS[/COLOR][/B] time
  [B][COLOR=#9932cc]FROM[/COLOR][/B] [COLOR=Black][B]table[/B][/COLOR]
  [B][COLOR=#9932cc]WHERE[/COLOR][/B] time [B][COLOR=#9932cc]BETWEEN[/COLOR][/B] %u [B][COLOR=#9932cc]AND[/COLOR][/B] %u
  [B][COLOR=#9932cc]GROUP[/COLOR][/B] [B][COLOR=#9932cc]BY[/COLOR][/B] [B][COLOR=#9932cc]TO_DAYS[/COLOR][/B][COLOR=#9932cc]([/COLOR][COLOR=#9932cc][B]FROM_UNIXTIME[/B]([/COLOR]time[COLOR=#9932cc])[/COLOR][/FONT][FONT=Courier New][COLOR=#9932cc])[/COLOR][/FONT][FONT=Courier New][COLOR=#9932cc]
)[/COLOR][/FONT][FONT=Courier New][B][COLOR=#9932cc]
ORDER[/COLOR][/B] [B][COLOR=#9932cc]BY[/COLOR][/B] time [B][COLOR=#9932cc]DESC[/COLOR][/B];[/FONT]
Das is aber irgendwie doch sehr DB-intensiv, wenn ich das richtig sehe.

Meine nächste Überlegung war es, einfach alle Datensätze im Intervall zu selektieren und dann in PHP nur das zu verarbeiten, was ich brauch.
Aber ob das wirklich besser is ? :think:

Fragen:
  1. Wie würdet ihr das Problem lösen ?
  2. Spätestens, wenn ich den ersten Wert z.B. eines jeden Vierteltages (nächster Datensatz zu 0:00, 6:00, 12:00, 18:00 Uhr) haben will, funktioniert der erste Ansatz nicht mehr. Kann ich das Problem allgemein in der DB lösen ? Falls nein, würde es eh auf die zweite Überlegung hinauslaufen
 
zunächst solltest du das date format nutzen und timestamp nicht mehr als int speichern. das ist zwar relativ typisch für php-scripte, aber für dbs eher nicht das optimum.

ansonsten kann ich dir auf mysql ebene hier keine besseren tips geben, das selbe problem habe ich bei größeren datenbeständen auch nicht effektiv lösen können. mein lösungsweg war der selbe..
(bei 150'000 datensätzen hat die antwort 2-3 sekunden gedauert, wobei das nicht der stärkste server ist.)

- performance kannst du maximal noch dadurch erreichen, indem du den gesamten wertebereich direkt im subselect einschränkst.
- wenn du die selben daten mehrfach benötigst, dann lasse per cronjob das select in einer tabelle persistieren
- 0, 6, 12, 18.. uhr daten kannst du durch sortierung der datensätze, date_format und werte-einschränkung erreichen.

wenn du auf andere dbms ausweichen kannst, wäre ein test von postgresql interessant. oracle hat mit sowas keine probleme, daher meine vermutung das postgresql das besser bewältigen könnte.
 
Zuletzt bearbeitet:
zunächst solltest du das date format nutzen und timestamp nicht mehr als int speichern. das ist zwar relativ typisch für php-scripte, aber für dbs eher nicht das optimum.
Ich hatte mich da aus speichertechnischen Gründen für INT entschieden, da der nur die Hälfte von einem DATETIME braucht.
- performance kannst du maximal noch dadurch erreichen, indem du den gesamten wertebereich direkt im subselect einschränkst.
Das WHERE ... BETWEEN is bereits im Subselect.
- 0, 6, 12, 18.. uhr daten kannst du durch sortierung der datensätze, date_format und werte-einschränkung erreichen.
Problem is aber, ich kann mich nicht darauf verlassen, dass wirklich Daten da sind (cronjob.de is auch ned 100%ig verlässlich). Worst-case wäre also, dass z.B. um 00:23 Uhr ein Datensatz is, der nächste aber erst um 13:42 Uhr, der dann für 12 Uhr zählen müsste und für 6 Uhr fehlt der Datenpunkt.

Ich möchte halt später beim Auswerten der Daten beliebige "rein- und rauszoomen" können.
wenn du auf andere dbms ausweichen kannst, wäre ein test von postgresql interessant. oracle hat mit sowas keine probleme, daher meine vermutung das postgresql das besser bewältigen könnte.
DBMS is fest: MySQL.
 
also ich verstehe net warum du nen subquery nutzt, zudem ist "GROUP BY TO_DAYS(FROM_UNIXTIME(time))" sehr ineffektiv, da MySql dafür keinen Index nutzen kann
 
Code:
[LEFT][FONT=Courier New][B][COLOR=#9932cc]SELECT[/COLOR][/B] time, data
[B][COLOR=#9932cc]FROM[/COLOR][/B] [COLOR=Black][B]table[/B][/COLOR]
[/FONT][FONT=Courier New][B][COLOR=#9932cc]WHERE[/COLOR][/B] time [B][COLOR=#9932cc]BETWEEN[/COLOR][/B] %u [B][COLOR=#9932cc]AND[/COLOR][/B] %u
[B][COLOR=#9932cc]GROUP[/COLOR][/B] [B][COLOR=#9932cc]BY[/COLOR][/B] [B][COLOR=#9932cc]TO_DAYS[/COLOR][/B][COLOR=#9932cc]([/COLOR][COLOR=#9932cc][B]FROM_UNIXTIME[/B]([/COLOR]time[COLOR=#9932cc])[/COLOR][/FONT][FONT=Courier New][COLOR=#9932cc])
[/COLOR][/FONT][FONT=Courier New][B][COLOR=#9932cc]ORDER[/COLOR][/B] [B][COLOR=#9932cc]BY[/COLOR][/B] time [B][COLOR=#9932cc]DESC[/COLOR][/B];[/FONT][/LEFT]
Damit ist mir zwar nicht zugesichert, dass ich auch wirklich die Minimal-Zeit eines jeden Tages hab, es funktioniert aber trotzdem, da die Datensätze chronologisch eingefügt worden sind.
 
also bei mir hatte das im test nicht die gewünschten zeilen gebracht. das datum stimmte zwar, die übrigen felder aberteilweise nicht.. *hm..