# Große Datenbank (MySQL) (Rangliste) sortieren per Cronjob



## Marius Heil (9. Oktober 2005)

Hi,

ich hab eine recht große Tabelle mit Usern in MySQL.
Diese möchte ich per CronJob nach Usern sortieren lassen.
Jetzt tauchen da ein paar Fragen auf:
1. Was mach ich mit der max_execution_time oder wie immer das auch heißt.
2. Ich muss zum sortieren die ganze Tabelle mit dem PHP Script einlesen und sortieren, von der Logik her muss der Server das also alles in den Speicher laden und sortieren.
Was kann ich da am besten machen, dass das dem nicht zu viel wird?
3. Besteht da nicht die Gefahr des Datenverlusts?
Vielleciht tauchen noch weitere Fragen auf, aber ich glaube, das ist erstmal der Großteil.
Würd mich freuen, wenn ihr Ideen hättet, ich mag nicht einfach druaf losprogrammieren und hinterher wird dem Server die Datenmenge zu groß,....


Marius


----------



## hpvw (9. Oktober 2005)

Warum willst Du das machen?

```
SELECT * FROM Tabelle ORDER BY User
```
erledigt das doch live bei der Abfrage und Du hast keine Gefahr des Datenverlusts.

Gruß hpvw


----------



## Marius Heil (9. Oktober 2005)

Nenenene, das wäre ja schon zu einfach 
Es geht darum, meine Rangliste kann zb:
- Nach bestimmten Rängen suchen
- Bestimmte Benutzer nach Kriterien finden
- Die Rangliste durchblättern
Da ich für alle Optionen jeweils Benutzer, Rang, Geld, usw,... brauche muss die Datenbank vorsortiert sein. Ich kann zwar auch Live ne Abfrage ausführen, die mir das ganze durchrechnet, aber das ist 1. kompliziert und 2. meckert der Server dann, wenn er das für jede Abfrage machen darf.
Ich muss also per Cronjob die Liste täglich aktualisieren lassen.


Marius
---
PS: Jetzt erinner ich mich, du hattest mir damals schon geholfen, es ist die gleiche Rangliste.
Das was du mir gesagt hattest, hab ich ne ganze Weile verwendet, allerdings gabs dann noch Probleme mit den unterschiedlichen Dateiversionen und der Server hat sich auf diese Weise überarbeitet, ganz so flexibel wars auch nicht. Danke nochmal für die Lösung, aber ich musste sie schlussendlich verwerfen, tut mir leid.#
---
Edit: Zu deiner Signatur: Ich benutz MySQL irgendwas mit 4.0


----------



## hpvw (9. Oktober 2005)

Ich habe gerade mal einen Test gemacht.
Zwei Tabellen mit je drei Feldern.
Eine ID, ein Textfeld und ein INT nach dem sortiert wird.
In der einen Tabelle stehen die Datensätze in zufälliger Reihenfolge, in der anderen werden sie entsprechend der Reihenfolge des INT-Felds eingetragen.
Es stehen die gleichen 10000 Datensätze, natürlich in verschiedener Reihenfolge, in der Datenbank.
Das INT-Feld hat einen Index.
Bei SELECT * FROM ordertable ORDER BY sortFeld macht es keinen zeitlichen Unterschied, aus welcher Tabelle ich die Daten auslese.
Daher Frage ich mich, warum Du den Aufwand betreiben und die Daten sortiert in die Tabelle eintragen willst.

Gruß hpvw


----------



## Marius Heil (9. Oktober 2005)

Mhhh, ich hab jetzt nicht ganz kapiert, was du gemeint hast.
Ich kann natürlich 2 Tabellen anlegen und das dann per PHP Script von 1er Tabelle in eine andere schreiben und zwar sortiert, da brauch ich keine Angst haben, dass es Datenverlust gibt, weil die 2. noch da wäre.
Ich hab eine Tabelle, da hab ich unter anderem drin:
Geld, Punkte, Username,....
Wenn ich die nicht sortiere,  dann muss ich mit jeder Anfrage erst ausrechnen lassen, wer welchen Rang hat, weil ich mag ja als Anfrage zb:
Gib mir bitte Rang 44-53 aus.
Das geht nur, wenn ich ne zusätzliche Spalte mit Rang mach, allerdings verändert sich der Rang ja, wenn einer neue Punkte bekommt.
Um die Ränge zu bestimmen muss ich ja die ganze Tabelle durchsorteiren lassen, oder?


Marius


----------



## hpvw (9. Oktober 2005)

Ich wollte mit dem Test nur zum Ausdruck bringen, dass es ziemlich belanglos ist, ob eine Tabelle bereits in sortierter Form vorliegt oder nicht.


			
				Marius Heil hat gesagt.:
			
		

> ... Diese möchte ich per CronJob nach Usern sortieren lassen. ...


Was Dir weiterhilft ist etwas anderes. Du musst nur (entgegen der Normalisierung, aber aus Performancegründen offensichtlich ratsam) eine weitere Spalte anlegen, die Du Rang nennst und jedesmal neu berechnest, wenn sich an den für dieses Feld relevanten Daten etwas ändert, also eine Art Caching-Mechanismus. Dabei musst Du keine Datenverluste befürchten und benötigst auch keine Cron-Jobs.

Gruß hpvw


----------



## cameeel (9. Oktober 2005)

Marius Heil hat gesagt.:
			
		

> weil ich mag ja als Anfrage zb:
> Gib mir bitte Rang 44-53 aus.
> Das geht nur, wenn ich ne zusätzliche Spalte mit Rang mach, allerdings verändert sich der Rang ja, wenn einer neue Punkte bekommt.
> Um die Ränge zu bestimmen muss ich ja die ganze Tabelle durchsorteiren lassen, oder?


 
 Vielleicht verstehe ich dich ja falsch aber würde es denn nicht so gehen:

```
SELECT * FROM table ORDER BY punkte DESC LIMIT 44, 53
```


----------



## Marius Heil (10. Oktober 2005)

Hi,

kann zwar einiges Programmieren, aber an manchen Stellen hab ich als die blödesten Lücken, wie zb in Flash, damit hab ich 1 Jahr gearbeitet und programmiert und alles und wusste nicht, dass die movieClips ne eigene Zeitleiste haben,d ei ich benutzen kann 
@cAm3eel: "DESC LIMIT 44, 53" was hat die Zahl nach dem Komma für eine Wirkung?
Soweit ich das mitbekommen hab, ist lediglich die Ausgabe, die ich dann bekomme sortiert, allerdings hab ich, wenn der bei jeder Abfrage die ganze Datenbank durchgehen muss, glaub ich nen größeren Performanceverlust.
@all: Wäre es in dem Zusammenhang nicht auch besser, wenn ich die Datenbank komplett durchsortieren würde?
Dann müsste er zb bei ner Abfrage anch Rang 56-73 nur bis zu Rang 73 die Liste durchgehen und nicht die ganze Liste von sagen wir 2000 nach den Rängen absuchen, die dazwischenliegen.
@hpvw: Die Spalte namens Rang hab ich schon, ich muss also lediglich noch per Cronjob die Felder mit Rang neu schreiben, dzau les ich alles aus und sortier das mit PHP, wobei ich  danach die neuen Ränge in die Datenbank schreib.
Wie ist das, wenn gerade User online sind und der schreibt grad die Ränge um, sollte nicht groß auffallen, oder?
Vielleicht ists etwas langsamer,....
Wieso meinst du, ich bräuchte keine Cronjobs?



Marius


----------



## hpvw (10. Oktober 2005)

Marius Heil hat gesagt.:
			
		

> Wieso meinst du, ich bräuchte keine Cronjobs?


Weil es keinen Sinn macht, die "Sortierung" einer Datenbank einmal täglich zu ändern, wenn möglicherweise mehrmals täglich Daten geändert werden oder auch mal ein paar Tage gar keine Änderungen vorkommen.
Es geht doch auch nicht darum die Tabelle vorzusortieren. Wie mein Test zeigt, hat es nahezu keinen Einfluss, in welcher Reihenfolge die Datensätze in der Datenbank stehen, wenn auf dem Feld, nach dem sortiert wird, ein Index liegt.
Es geht nur darum, die zeitintensive Berechnung des Ranges nicht bei jeder Abfrage durchzuführen.
Um nach Änderungen am Datenbestand nicht bis zum Cronjob falsche Ränge zu präsentieren, muss der Rang nach jeder relevanten Änderung neu berechnet und in der Tabelle gespeichert werden. Damit ist der Cronjob dann überflüssig.

Gruß hpvw


----------



## cameeel (11. Oktober 2005)

Marius Heil hat gesagt.:
			
		

> @cAm3eel: "DESC LIMIT 44, 53" was hat die Zahl nach dem Komma für eine Wirkung?


  Ich dachte immer so werden die Datensetze zw. 44 und 53 ausgegeben, nach Punkten geordnet halt... hab ich mich geirrt?



			
				Marius Heil hat gesagt.:
			
		

> @cAm3eel: Soweit ich das mitbekommen hab, ist lediglich die Ausgabe, die ich dann bekomme sortiert, allerdings hab ich, wenn der bei jeder Abfrage die ganze Datenbank durchgehen muss, glaub ich nen größeren Performanceverlust.


  Stimmt, gut möglich 


  cAm3eel


----------



## vop (11. Oktober 2005)

Hi Marius

  ich möchte einmal die Äußerungen von hpvw unterstützen. 
  Du brauchst sicher keine tägliche Sortierung durchführen, dazu verwendet man Indexe.

  Eine angepaßte SQL-Abfrage fördert Dir alles zu Tage, was du benötigts.

 Übrigens ist die Variante mit LIMIT eine gute Lösung, aus einer sortierten Tabellen die Einträge 44 bis 53 zu erhalten. (Siehe MySQL-Referenz)

  cAm3eel lag also vollkommen richtig
*select * from tabelle ORDER BY PUNKTE LIMIT 43,53;  # Zeilen 44 bis 54 zurückgeben*   Und dann interessiert mich doch noch  folgendes:


> ich hab eine recht große Tabelle mit Usern in MySQL.


  Wie groß ist denn die Tabelle?


  Ich vermute, dass Sie weit weniger als 1000000 Datensätze haben wird, oder?
  Von daher ist die Tabelle nicht wirklich groß. 

 Deine Performance-Sorgen sind vermutlich völlig unberechtigt.


  Mein Fazit:
  Vergiss die cronjobs und die Sortierarbeit.
  Lass Dir die Tabelle durch einen geeigneten SQL-Befehl in der gewünschten Form ausgeben.
  Investiere lieber ein wenig Zeit, SQL besser zu verstehen, dann entdeckst Du dort eine Menge Möglichkeiten.

  vop


----------



## hpvw (11. Oktober 2005)

Nur, um Missverständnisse aus dem dem Weg zu räumen:
	
	
	



```
... LIMIT 44,53
```
ermittelt 53 Zeilen ab der 44. Zeile, wobei die Zeilennummer 0 die erste Zeile darstellt, und nicht die Zeilen Zeilen 44 bis 53.
Zumindest steht das so im Handbuch.

Gruß hpvw


----------



## vop (11. Oktober 2005)

> Nur, um Missverständnisse aus dem dem Weg zu räumen:  	Code:
> ... LIMIT 44,53​
> ermittelt 53 Zeilen ab der 44. Zeile, wobei die Zeilennummer 0 die erste Zeile darstellt, und nicht die Zeilen Zeilen 44 bis 53.


 
 absolut korrekt, mein Fehler, sorry.

 vop


----------



## cameeel (11. Oktober 2005)

vop hat gesagt.:
			
		

> absolut korrekt, mein Fehler, sorry.
> 
> vop


 
 Ne eigentlich wars mein Fehler 

 Aber egal der Ansatz war richtig ^^


 cAm3eel.


----------



## nauv (11. Oktober 2005)

Schreib ein PHP script und lass es per Cron ausführen *g*


----------



## Marius Heil (11. Oktober 2005)

@nauv: Öhhhhm, jop 
Alllso, kurzes Summary:
-Limit 44,53 ist nicht zu gebrauchen, da es was anderes macht.
-Mhh, MySQL besser lernen, nun ja, ich hab einige Bücher über PHP gelesen, da war MySQL immer ein wenig dabei. Bisher reichen mir meine Kenntnisse eigentlich völlig aus, Abfrage, Update, Löschen,....
Wie groß die Tabelle wird, kann ich net sagen, derzeti ist sie noch klein, aber wenn MySQL so viel schafft, bruach ich da wohl wirklich net so viel Angst haben. Ich denk mir nur immer, wie der PC so viele Daten durcharbieten soll,...
Nun aber:
Wenn ich wegen jedem User, der gerade 3 Pünktchen bekommen hab die ganze Ränge in der MySQL Liste neuschreiben muss, das kommt mir net gesund vor.
Bei den Cronjobs müsste ich es nur in bestimmten Abständen machen, selbst wenn ich das jede Stunde mach, kommt der Server noch deutlich besser weg, als mit dauernder Umschreibung.
Ich hab das in mehreren Onlinespielen bemerkt, dass die Ranglsite immer erst nach ner Zeit wieder stimmt, das muss doch nen Grund haben.
Gibts in MySQl nen Befehl dafür, dass ich Zeilen verschieben kann?
Das wäre das beste, ich würde eifnach bei jedem Punktegewinn die Zeile an die richtige Stelle der Tabelle schieben, mit ner Rangspalte geht das eher schelcht, wenn ich was verschieb, muss ich immer die gnazen zahlen ändern.


Marius


----------



## hpvw (12. Oktober 2005)

Marius Heil hat gesagt.:
			
		

> Gibts in MySQl nen Befehl dafür, dass ich Zeilen verschieben kann?


Nein gibt es nicht. Du müsstest alles auslesen, sortieren, löschen und neu eintragen.
Wie ich oben erwähnt (und mehrfach wiederholt) habe, bringt das für die Performance beim Auslesen gar nichts. 
Ein Index auf der zu sortierenden Spalte bringt Dir (in oben dargestellter Testumbegung) eine Beschleunigung um ungefähr das dreifache.
Query-Cache zu aktivieren hilft, dass auch eine Tabelle ohne Index nur einmal nach jeder Änderung langsam ausgelesen wird und dann genauso schnell, wie mit Index, ist.

Gruß hpvw


----------



## vop (12. Oktober 2005)

Hi Marius

 Nochmal zum mitlesen

 1. Wenn ein User Punkte macht: UPDATE der PUNKTE für den User - fertig
 (Kein RANKING speichern!)
 2. Wenn Du das Ranking anzeigen willst (oder sonst irgend etwas) entsprechendes SELECT
     mit ORDER BY PUNKTE - fertig

 Eine sonstige Sortierung ist nicht nötig, das geschieht durch geeignetes Select und ggf. INDEXEN!

 Das Speichern des Rankings ist nicht nötig, im Gegenteil eher hinderlich!

 Das Ranking kannst du online ermitteln, wenn Du nach PUNKTEN sortierst

 Die Plätze 10 bis 20 erhälst du beispielsweise mit
 SELECT * FROM TABELLE 
 ORDER BY PUNKTE
 LIMIT 9,10

 Das sind vom 10. Eintrag beginnend 10 Einträge.

 Alles klar?

 vop


----------



## Marius Heil (4. November 2005)

Aaalso, tut mir leid, dass ich so ewig nicht mehr geantwortet habe. Hab erst jetzt mitbekommen, dass es neue Beiträge gibt.
Ich glaub, ich muss nochmal von vorne anfangen 
Hab inzwischen alles andere Programmiert, nur nicht die Sortierung.
Das was vop da gerade zusammengefasst hat, stimmt nicht grad, bin ich der Meinung.
Wenn ich diese Anfrage hier:


> SELECT * FROM TABELLE
> ORDER BY PUNKTE
> LIMIT 9,10


Ausführe, liest mir die MySQL Datenbank alle Datensätze von 10 bis 20 aus. Ich hab zwar nicht allzuviel MySQL gelesen, allerdings hatte ich schonmal getestet, was Order by macht. Das Ordnet mir alle !Ausgelesenen! Datensätze nach bestimmte Kriterien, jedoch nicht die Tabelle vor dem Auslesen, ich bekomme also dadurch 10 zufällige Datensätze.
Ich bin deshalb der Meinung, es ist unbedingt notwendig eine Spalte namens Rang anzulegen, die ich auch schon habe.
Nun mache ich jedes mal eine Umsortierung, wenn ein User Punkte bekommt, weil ihr meintet, das ist nicht Performancelastig.
Allerdings: Wenn ich sagen wir mal 5000 User habe, nur als Beispiel, dann ist Rang 15 plötzlich auf 14 gerutscht. Dann muss ich doch einfach nur den Rang auf 14 umschreiben und folglich alle User, die dazwischenliegen +1 machen.
Meinen da alle das selbe?


Marius


----------



## hpvw (4. November 2005)

Marius Heil hat gesagt.:
			
		

> Ausführe, liest mir die MySQL Datenbank alle Datensätze von 10 bis 20 aus. Ich hab zwar nicht allzuviel MySQL gelesen, allerdings hatte ich schonmal getestet, was Order by macht. Das Ordnet mir alle !Ausgelesenen! Datensätze nach bestimmte Kriterien, jedoch nicht die Tabelle vor dem Auslesen, ich bekomme also dadurch 10 zufällige Datensätze.


Wie es auch die Reihenfolge in der Syntax andeutet, wird LIMIT erst nach der Sortierung angewendet.



			
				Marius Heil hat gesagt.:
			
		

> Ich bin deshalb der Meinung, es ist unbedingt notwendig eine Spalte namens Rang anzulegen, die ich auch schon habe.
> Nun mache ich jedes mal eine Umsortierung, wenn ein User Punkte bekommt, weil ihr meintet, das ist nicht Performancelastig.
> Allerdings: Wenn ich sagen wir mal 5000 User habe, nur als Beispiel, dann ist Rang 15 plötzlich auf 14 gerutscht. Dann muss ich doch einfach nur den Rang auf 14 umschreiben und folglich alle User, die dazwischenliegen +1 machen.
> Meinen da alle das selbe?


Das verstehe ich nicht, aber ich glaube, Du verrennst Dich.

Gruß hpvw


----------



## vop (7. November 2005)

Hi Marius

 Vielleicht solltest Du wenigstens versuchen, Hilfe anzunehmen.
 Mit deiner Aussage:


			
				Marius Heil hat gesagt.:
			
		

> ...
> Das was vop da gerade zusammengefasst hat, stimmt nicht grad, bin ich der Meinung.
> Wenn ich diese Anfrage hier: ...
> Ausführe, liest mir die MySQL Datenbank alle Datensätze von 10 bis 20 aus....ich bekomme also dadurch 10 zufällige Datensätze....


 widersprichst Du Dir selbst.
 Hast Du es eigentlich einmal probiert?
 Du bekommst mit Sicherheit nicht die Einträge 10 bis 20, denn das wären ihrer 11! 

 Außerdem findet die Sortierung definitiv vor der Übertragung und vor dem LIMIT statt.

 Du darfst natürlich auch gerne deine eigene Sortierung programmieren, aber Du könntest es auch einfacher haben.
 Gruß vop


----------



## Marius Heil (8. November 2005)

Hi,

ich hatte es schonmal probiert, konnte nicht eher antworten, da tutorials.de abgestürzt war.
Ich denke, ich programmier mir jetzt einfach mal ne sortierung und poste die dann hier, hab schon was im Kopf, dann könnt ihr mir hinterher sagen, was ich anders machen könnte 
Ich weiß nämlich nicht genau, worauf ihr herauswollt. Aber vielen Dank nochmal für die Antworten, ich hoffe, ich komm in den nächsten paar Tagen zum programmieren, da ich mich in der Schue nicht mehr vor Arbeiten retten kann.



Marius
---
Mhhhh, tut mir wirklich Leid, dass ich euch so viel Zeit genommen hab, aber ganz offenbar scheint eure Lösung doch zu funktionieren  :-( 
Aber ich denke, wenn ich dann zb nach nem Benutzername suche und dazu noch alle Ränge ausgeben will, die 7 drüber und 7 drutner leigen, bekomm ich doch ein problem, nicht?


----------



## Marius Heil (27. Februar 2006)

So,

ich hab inzwischen ziemlich viel weiterprogrammiert, was aber die ganze Zeit auf der Strecke gebleiben ist, ist die Ranglistensortierung 
Naja, ich glaube, es stimmt doch, wenn man das ganze mit ORDER BY macht, nun aber die Frage, was mache ich, wenn ich haben will:
Einen bestimmten Usernamen und die 7 Ränge drunter und die 7 darüber?
Frage 2:
Was mache ich, wenn ich haben will:
Ich suche nun mit LIKE und zwar zb nach dem Suchbegriff "sdf", nun bekomme ich sagen wir mal 5 Ergebnisse, wie schaff ichs nun, dass ich mit der Abfrage auch noch die Ränge der User dazubekomm?


Marius


----------



## Marius Heil (3. März 2006)

Jemand ne Idee


Marius


----------



## hpvw (3. März 2006)

Der Rang entspricht bei der richtigen Sortierung der Zeilennummer.

Für Deine 7 vorher und nacher brauchst Du ein Subquery oder einen entsprechenden Workaround.

Gruß hpvw


----------



## Radhad (3. März 2006)

Also ich merke schon, dass du, Marius, nicht allzu viel Erfahrung in SQL hast. Das ist auch nicht weiter schlimm. Ich bau dir mal ein kleines Beispiel  Ich denke das lässt sich Anschauung gut verwenden, melde mich später nochmal!

Im vorraus sei schonmal gesagt: Die SQL Anweisung "SELECT * FROM user ORDER BY punkte" liefert dir die komplette Rangliste!


Gruß Radhad


[EDIT]

Die erste Demo gibt es auf http://www.radhad.de

Infos zur table:
*Datensätze:* 1000
*SQL-String:* wird angezeigt
*UserID:* Primary Key, auto_increment
*Userame:* erstellt mit Zufallsgenerator
*Punkte:* erstellt mit Zufallsgenerator
*Ladezeit:* Wird mit microtime() ermittelt und am Ende ausgegeben

Wenn jemand schon eine Idee hat, wie man die 7 vor & nach dem User (UserID) bekommt, der möge dies hier posten, können wir ja dann testen.

Mein Tipp wäre, pro Seite 50 oder 100 Ränge anzeigen zu lassen und dann den User (UserID) fett hervorzuheben, und dem User direkt diese Seite präsentieren.

Sind mehr Datensätze erwünscht, kann ich Problemlos noch mehr hinzufügen!


----------



## misayre (13. März 2006)

Solange das ganze mit PHP programmiert wird sollte es keine große Hürde darstellen.

Man will einen User und die darumliegenden Plätze wissen.

Man baut sich eine Abfrage, welche den entsprechenden User ausgibt und seinen exakten Platz oder seine exakte Punktzahl.

Nun nimmt man diese Punktzahl und baut darauf aufbauend zwei Abfragen.
Eine in der die Punktzahl größer als die gegebene sein muß und wählt nur die ersten 7.
Eine in der die Punktzahl kleiner als die gegebene sein muß und wählt nur die ersten 7.

Schon hat man den betreffenden User und 7 darumliegende Plätze.

Die Ausgabe dafür zu bauen ist dem Geschmack freigestellt.


Alternativ könnte man auch die komplett sortierte Rangliste in ein Array drücken und dieses per Index ansteuern. Sobald man den Index hat, welcher dem gewünschten User entspricht ist es ein Klax von diesem Index die 7 vorhergehenden und die 7 nachfolgenden zu wählen. Das würde ich jedoch nur empfehlen, wenn die Datenmengen sich in Grenzen halten.


----------



## Marius Heil (13. März 2006)

Mhhhh, ja, du ahst recht, so geht das, aber ich glaube fast, dass eine einzelne Anfrage Ressoursenschonender wäre.
Verzeit mir, dass ich so spät antworte, ich dreh zurzeit nen Film und jetzt ist grad der Endspurt, das ganze Material zusammenschneiden, mit effekten versehen, usw.....
Nicht mehr allzuviel Zeit.


Marius


----------



## misayre (13. März 2006)

Um ehrlich zu sein kann ich deine Angst vor mehreren SQL-Abfragen nicht verstehen. Die Performance einer SQL-Abfrage ist um längen besser als wenn du mit wirklich großen Arrays in PHP rumwurschtelst. 

Die Laufzeiten in einem kleinen Projekt werden sich nichts nehmen, wenn du mit deinem Projekt jedoch einst wirklich richtig große Zahlen hast, dann wird es sehr schnell sinnvoller zu sein mehr Abfragen per mySQL zu machen als mit großen Arrays in PHP zu arbeiten. Nicht nur dein RAM wird es dir danken.

Du solltest nicht vergessen, daß mySQL hochgradig optimiert ist. Das trifft selbstverständlich auch auf andere Datenbanksysteme zu, wobei da jeder so seine eigenen kleinen Besonderheiten aufweist, die der Ottonormalprogrammierer in den seltensten Fällen ankratzt.

Oftmals wirst du feststellen, daß die Performance nicht unter der Anzahl an Abfragen leidet sondern wie gut deine Abfrage auf den zu leistenden Sachverhalt optimiert ist. Genauso wirst du eher Performancelecks in deiner PHP-Algorithmik haben als sonstwo, denn nichts ist kniffliger als wirklich gut optimierten Code zu schreiben, denn hier muß man überhaupt erstmal wissen auf welche Werte man optimieren will. Speichernutzung, Geschwindigkeit und so weiter und so fort, denn sie korrelieren nur selten direkt miteinander, sondern beeinflussen sich meist antiproportional.

Wenn ich deine Posts lese und ich hoffe du nimmst mir das jetzt nicht sofort übel, habe ich den Eindruck als ob du dir große Projekte aufhalst, sie perfekt machen willst und dir vor der Fertigstellung dann ein anderes Projekt in die Quere kommt. Sollte das zutreffen, dann müßtest du deinen Perfektionismus kanalisieren und nur auf Teilaspekte loslassen, aber nicht auf das Ganze. Aber natürlich kann da meine Hobbypsychologie auch total fehl gehen ^^


----------



## Marius Heil (15. März 2006)

Hi,

das Projekt ist reichlich groß, soweit so gut, mit den mehreren Projekten gleichzeitig leigst du auch nciht falsch, ich bekomm jedoch alle fertig, nur dass in den letzten paar Tagen des Filmens das andere mal etwas warten muss, naja, solange hat der Zeichner Zeit ^^
Das Problem ist bei mir einfach, dass ich alles mach^^
Programmieren, Filmschneiden, 3D, demnächst mag ich ein eigenes Lied komponieren (Naja, tu ich zurzeit schon, aber Instrumental) das nächste wird mit Gesang, usw,...
Wenn der FIlm fertig ist, werd ichs höchstwahrscheinlich mit deinem Vorschlag ausprobieren, scheint doch ganz passabel ^^
Es ist nciht so, dass ich mit großen Arrays rumwerkel, die größten arrays haben 40 Zeichen insgesamt oder so^^ Dachte nur, wenn man die MySQL Anfrage entsprechend formuliert, bekommt man das Ergebniss mit einer Abfrage.


Marius


----------



## misayre (15. März 2006)

Ein großes Array heißt nicht, daß die einzelnen Einträge groß sind, sondern vielmehr, daß man ein sehr große Anzahl von Einträgen hat. Wenn man 2 Mio Datenbankeinträge hat und die alle in ein Array stopft und dann mit dem Array arbeitet, dann ist es ein großes Array. An der Stelle wäre es sinnvoller nicht mit einem Array zu arbeiten.


----------



## kahra (16. März 2006)

Also du kannst auch sowas machen:

Lege dir die Tabelle noch ein 2tes mal an und nenne sie z.B. table_temp;
von der Datenstruktur die aber die gleiche wie die orig Tabelle.

dein phpscript für dein cronjob könnte so aussehen:

```
<?php
mysql_query("INSERT INTO table_temp SELECT * FROM table_orig");
mysql_query("DELETE FROM table_orig");
mysql_query("INSERT INTO table_orig SELECT * FROM table_temp ORDER BY rang");
?>
```

Wenn du aber einen Server hast den du z.B. per ssh konfigurieren kannst und die Conrjobs mit crontab konfigurieren kannst dann mache das lieber so:

Lege eine sql-Datei, z.B. sortiere.sql, in der folgende Zeilen stehen

```
INSERT INTO table_temp SELECT * FROM table_orig;
DELETE FROM table_orig;
INSERT INTO table_orig SELECT * FROM table_temp ORDER BY rang;
```

Die Datei kannst du dann aufrufen in etwa damit *mysql DATENBANK < /Pfad_zu_Datei/sortiere.sql*

Die Zeile brauchst du dann nur zu deinen Crons hinzufügen und ne passende Zeit davor setzen.

Versuche so viel wie möglich mit mySQL zu machen statt mit php, das ist wesentlich schneller.

Aber sinnlos ist das allemal. Wenn deine Rangliste sowieso nur einmal am Tag aktuallisiert werden soll, erzeuge doch um Mitternacht oder sonstwann einfach ne statische HTML-Datei in der alles drinne steht. Oder halt mehrere wenn nicht alle nutzer auf einer Seite angezeigt werden sollen. 

Wenn du den Rang als Index setzt kannst du mit *OPTIMIZE TABLE table_orig*
das sortieren lassen. Ist wahrscheinlich die bessere Variante, aber schau dazu noch mal ins Manual auf Seite 773 (deutsch pdf).


----------



## misayre (16. März 2006)

Halten wir doch einfach das fest, was jeder bisher zu sagen wußte - die Optimierung von mySQL ist aktuell besser als das, was wir mit einer einfachen Sortierung einer Tabelle erreichen würden und nur sortieren um sortiert zu haben? Ich weiß nicht. Das erscheint mir dann eher wie vergebene Performance.


----------



## Marius Heil (16. März 2006)

Jop, Cronhjob hab ich bereits verbannt, das wäre nicht sonderlich schwer zu programmieren gewesen, aber ist unsinnig.
Ich weiß schon,w as Arrays sind und arbeite bei den MySQL abfragen nur mit Arrays die höchstens 14 Einträge oder so enthalten, ich arbeit also da nciht mit Datenmassen, keien Angst, so blöd bin ich net 
Die ganze Datenbank zuerst per PHP auslesen und dann bearbeiten wäre totaler Schwachsinn, deshalb wollte ich ne gute MySQL Abfrage, welches das an einem macht, aber die Methode mit 3 Abfragen könnte auch gehen, ich würd da sogar mit 2 auskommen, glaub ich..

Marius


----------



## Marius Heil (6. Juli 2006)

Tut mir wirklich Leid, hab sehr viel Weiterprogrammiert aber an der Sortierung Hakts immer noch 
Es gibt mehrere Anfragearten:
1. Anfrage nach Rang: Ich benutze bei Rang 15 zb einfach die Anfrage: SELECT * FROM user ORDER BY Punkte LIMIT 8,14
Das Stimmt so weit und geht auch.
2. Anfrage nach einem bestimmten User: Ich lese aus, wie viele Punkte der User hat, stelle daraufhin mit PHP 2 Weitere anfragen, einmal kleiner als die Punkte, einmal größer und dann jeweils die ersten 7.
Das ist soweit auch klar.
3.Anfrage mit einem Teilstring des Usernamens: Jetzt wirds kompliziert. Es klappt ja so weit, als dass ich die User, die zutreffen mit einer WHERE name LIKE,... abfragen kann, aber wenn ich nun noch den Rang für jeden User haben möchte, wird das zu einem Problem. Wie kann ich, ohne für jeden User ne Extra Anfrage zu stellen den Rang rausbekommen?
Was das sinnigste wäre wäre, dass MySQL bei dem Durchgehen durch die Datenbank gleich die Zeilen mitzählt oder so, wie ich das Anstell weiß ich noch nicht. Habt ihr da eine Idee?


Marius


----------



## Marius Heil (9. Juli 2006)

Hi,

mag nur nochmal nachfragen, ob jemand den Beitrag gelesen hat.

Marius


----------



## schizo1980 (8. August 2006)

jep, ich habe mir alles durchgelesen,
von 2005 bis juli 2006 

ich glaube aber das du um einen cron nicht herum kommen wirst
( jetzt wird es viele böse antworten geben  ).

ich habe mir auch ein paar spielen angeguckt und die benutzen offensichtlich 
cronjob für ihre ranglisten.
guckt euch das bild an, "johann" hat 213 punkte ist aber noch auf platz 1736
und nach rang 1736 kommt rang 1721. PHP schiebt ihn bei der ausgabe einfach nur nach oben, in der db aber nicht.
ich habe beobachtet das die rangliste etwas alle 1-2 minuten von dem server sortiert wird,
in der zwischenzeit stimmt nur die punktezahl, aber nicht der rang.

der screen stammt aus dem spiel travian ( 0,5 mio accounts weltweit ).
http://img159.imageshack.us/my.php?image=ranglistewk9.gif

PS: an was für einem projekt arbeitest du?


----------



## Marius Heil (11. August 2006)

Genau das ist es, was mich auch stuzig gemacht hat, dass das offenbar alle so machen. Hab zwar weiterprogrammiert am projekt, aber das Ranglistenproblem ruht immer noch 
Das Projekt, an dem ich immer noch bin ist ein Remake des Prügelpause, das es von Lycos vor einiger Zeit mal gab.
Du kannst mich ja mal in ICQ anschreiben, meine Nummer steht hier im Tutorials.de Profil drin.
Hier was kleines zum anschauen, das wird wohl eine Figur werden: http://img388.imageshack.us/my.php?image=b1uu7.swf Derjenige, der sie gezeichnet hat, wollte noch eine weitere Skizze erstellen und diese dann selbst vektorisieren, darauf warte ich im Moment noch, dann werd ich mich ans animieren machen.


Marius


----------



## schizo1980 (13. August 2006)

ich habe das jetzt so gelöst.

mysql_query("TRUNCATE TABLE rangliste");
mysql_query("INSERT INTO rangliste SELECT NULL, spielerID, spielername, kills FROM spieler ORDER BY kills");

die rangliste hat noch eine zusätzliche spalte mit dem namen "rang" und 
ist auf auto_increment eingestellt.


----------

