Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλημέρα!

Λοιπόν, έχουμε τον ακόλουθο κώδικα που υπολογίζει τα points ενός συστήματος "awards".

Ο πίνακας award έχει τα awards και ο award_user, τα δεδομένα του σε ποιον χρήση έχει δοθεί, ποιο award.

$userpoints = $db->query_first('
                SELECT award.*, award_user.*, SUM(award_pointvalue) AS TotalPoints, COUNT(award_user.issue_id) AS TotalAwards
                FROM ' . TABLE_PREFIX . 'award_user AS award_user
                LEFT JOIN ' . TABLE_PREFIX . 'award AS award USING (award_id)
                WHERE award_user.userid = '. intval($userid) . '
                AND award.award_active = "1"
                GROUP BY award_user.userid
            ');

$vbulletin->db->query_write("UPDATE " . TABLE_PREFIX . "user 
								 SET sc_awards_number = ". intval($userpoints['TotalAwards']) .",
									 sc_awards_points = ". intval($userpoints['TotalPoints']) ."
								WHERE userid = " . intval($userid) . "");

Το θέμα: ο παραπάνω κώδικας, μπορεί να θέλω να τρέξει, ας πούμε για κάποιες χιλιάδες userids σε μια while ( ; ) *

 

Έχετε να προτείνετε κάποια τροποποίηση στον κώδικα χάρην απόδοσης;

Κάτι που έχω κατά νου:

- Ίσως το $userpoints query μπορεί να ενσωματωθεί ως υποερώτημα στην UPDATE; Αν γίνεται κάτι τέτοιο, ποια η σύνταξη;

- Ακόμα πιο προχωριμένα: μπορεί να ενσωματωθεί ως υποερώτημα στην UPDATE + να μπει ένα "WHERE userid IN ();

 

* Βασικά για να σας δώσω να καταλάβετε τι θέλω να κάνω: θέλω για συγκεκριμένα award_ids να ενημερώσω το sc_awards_number και sc_awards_points του πίνακα user, για τους χρήστες που έχουν το/τα συγκεκριμένα award_id(s).

Αυτή τη στιγμή, τραβάω τους χρήστες από το award_user και σε μια php while τρέχω τον από πάνω κώδικα. Απλά όταν ένα ή περισσότερα awards έχουν 1000 δες χρήστες, νομίζω η προσεγγισή μου δεν είναι και η καλύτερη.

 

Κάθε βοήθεια ευπρόσδεκτη. :-)

Δημοσ.

Προσωπικά εγω θα έκανα ενα schedule task (ή ενα cron task αν είσαι σε Linux), οπου 1 ή 2 φορές την μέρα (αναλόγως τις ανάγκες σου) θα έκανε update τα sc_awards_number και sc_awards_points στην database σου. 

 

Με αυτό τον τρόπο θα μειώσεις το MySQL ερώτημα σου, αφού το update θα γίνεται με το schedule task και ουσιαστικά στην PHP σου θα κάνεις μονο ενα select. 

Δημοσ.

Βασικά το σύστημα λειτουργεί ως εξής: κάθε φορά που δίνεται ένα award σε κάποιον user (χειροκίνητη λειτουργία του διαχειριστή), για τον συγκεκριμένο χρήστη, ενημερώνονται τα points του.

 

Όμως αν ο admin αλλάξει τα points ενός award, θέλουμε να υπάρχει η παραπάνω δυνατότητα για συγκεκριμένα awardids, να γίνονται update τα points όσων χρηστών τα έχουν.

 

Πρόκειται στην ουσία για manual λειτουργία του admin και προτιμάμε να μη τη βάλουμε σε scheduled task.

 

Μπορούμε να το κάνουμε το εργαλείο να προσεσσάρει χρήστες σε παρτίδες κατά το run του script (= νέα σελίδα ανά Χ αριθμό χρηστών), απλά σκεφτόμουν μήπως υπάρχει κάποιος τρόπος με αποκλειστική χρήση ερωτήματος και υποερωτημάτων σε αυτό, να γίνει γρήγορα η διαδικασία ή να βελτιωθεί ο υπάρχων κώδικας, τουλάχιστον. :-)

Δημοσ.

Καλησπέρα, θα συμφωνήσω με το scheduled task.

 

 

Εννοείται πως εάν θέλουμε να γίνουν οι αλλαγές από τον admin μπορεί να τρέξει το script ή κάποιο υπό-script χειροκίνητα.

 

 

Για το query θα μπορούσε να γίνει η ενημέρωση με ένα query μπορείς να δεις στο google με το search term mysql update from select join” παραδείγματα.

 

 

Το θέμα για το γρηγορότερα βέβαια έχει να κάνει με πολλούς παράγοντες.

 

ΠΧ τι επίπεδο κανονικοποίησης έχει η βάση; Τι συσχετίσεις; Τι indexes;

 

 

Στην τελική ανάλυση θα πρέπει να γίνουν tests και να βρεθεί ο γρηγορότερος χρόνος εκτέλεσης για το εκάστοτε query ώστε να καταλήξεις κάπου και αυτό δεν γίνεται μέσα από το forum ;)

 

Δημοσ.

κάτι τέτοιο πολύ πρόχειρα δε σου κάνει?

χωρίς while, με in για να βάλεις τα id που θέλεις

update user 
set sc_awards_number = tmp.totalawards, sc_awards_points = tmp.totalpoints
from user inner join (
	SELECT award.*, award_user.*, SUM(award_pointvalue) AS TotalPoints, COUNT(award_user.issue_id) AS TotalAwards
	FROM award_user AS award_user
	LEFT JOIN award AS award USING (award_id)
	WHERE award_user.userid in ( ta userid pou 8es)
	AND award.award_active = "1"
	GROUP BY award_user.userid ) tmp on user.userid = tmp.userid

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...