While μέσα σε while υπάρχει πιο σωστός τρόπος;

Σε αυτή την περιοχή μπορείτε να βρείτε ή να αναζητήσετε πληροφορίες σχετικές με την PHP

Συντονιστές: WebDev Moderators, Super-Moderators, PHP Moderators

Απάντηση
alou
Script Master
Δημοσιεύσεις: 1374
Εγγραφή: 24 Αύγ 2007 19:52
Επικοινωνία:

While μέσα σε while υπάρχει πιο σωστός τρόπος;

Δημοσίευση από alou » 29 Μάιος 2012 18:16

Καλησπέρα :D

Αυτό που περιγράφω παρακάτω, ναι μεν δουλεύει αλλά από ένα σημείο και μετά καταναλώνει αρκετούς πόρους και σκέφτομαι αν υπάρχει ένας πιο resources friendly τρόπος να το αντιμετωπίσω:

-Ένας πίνακας στην mysql περιέχει user id, αριθμό κάρτας, πόντους κάρτας
-Από ένα remote xml, παίρνω αριθμό κάρτας και πόντους κάρτας για καθημερινή ανανέωση
(αρκετές χιλιάδες records, οι εγγραφές στη βάση είναι πολύ λιγότερες)

Κώδικας: Επιλογή όλων


//$tempvc = το query που παίρνω τις κάρτες που υπάρχουν καταχωρημένες στη βάση 
//$ptsUsed = από το XML, array με όλες τις κάρτες (κάρτα και πόντοι ανά record)
//$ptsUsed->PO_CardNumber η κάρτα και $ptsUsed->PO_Points οι πόντοι
	$dbPopulation = count($tempvc); //τόσες κάρτες υπάρχουν στη βάση
	$xmlPopulation = count($ptsUsed); // # records στο xml

	$i = 0;
        //loop στις κάρτες που υπάρχουν στη βάση
	while &#40;$i < $dbPopulation&#41; &#123;
		$ix = 0;
                //loop sto xml data gia na broume ti swsti karta
		while &#40;$ix < $xmlPopulation&#41; &#123;
			$updatePoints = $ptsUsed&#91;$ix&#93;->PO_Points;
			$currentCard = $ptsUsed&#91;$ix&#93;->PO_CardNumber;
                        //αν η κάρτα στο loop του xml είναι ίδια με αυτή του από πάνω loop, γίνεται update στη βάση με τους πόντους
				if &#40;$currentCard == $tempvc&#91;$i&#93; &#41; &#123; 
				//query gia update sti vasi
				&#125;
		$ix++;
		&#125;
	$i++;
	&#125;
Ευχαριστώ εκ των προτέρων όποιον μπει μόνο και μόνο στον κόπο να καταλάβει ... :D

Το ζητούμενο είναι αν υπάρχει κάποιος έστω τελείως διαφορετικός τρόπος, αλλά με τα ίδια δεδομένα δλδ update με βάση τα στοιχεία ενός remote xml που να οδηγεί σε λιγότερα db queries που είναι το κυρίως πρόβλημα.

Άβαταρ μέλους
Rapid-eraser
WebDev Moderator
Δημοσιεύσεις: 6851
Εγγραφή: 05 Απρ 2003 17:50
Τοποθεσία: Πειραιάς
Επικοινωνία:

While μέσα σε while υπάρχει πιο σωστός τρόπος;

Δημοσίευση από Rapid-eraser » 29 Μάιος 2012 20:34

Αρχικά αφού ξέρεις πόσα είναι τα βήματα που θα κάνεις αντικατέστησε τα while με for αν και η λογική που το έχεις στήσει δεν έχει κάποια πρακτική αξία.

Αφετέρου είναι πιο σύντομο απλά να προσθέσεις τις κάρτες με τους πόντους κατευθείαν σε ένα πίνακα και να κάνεις μετά τα aggregation / consuming που θες.

Επίσης μπορείς να χρησιμοποιήσεις statements του τύπου INSERT .... ON DUPLICATE UPDATE ....

Τέλος με χρήση foreign keys μπορείς να διασφαλίσεις ότι δεν θα μπει στο σύστημά σου κάρτα που δεν έχεις αποθηκεύσει.
Cu, Rapid-eraser, Tα αγαθά copies κτώνται.
Love is like oxygen, You get too much you get too high
Not enough and you're gonna die, Love gets you high

Άβαταρ μέλους
dva_dev
Script Master
Δημοσιεύσεις: 3790
Εγγραφή: 16 Σεπ 2005 01:32
Επικοινωνία:

While μέσα σε while υπάρχει πιο σωστός τρόπος;

Δημοσίευση από dva_dev » 29 Μάιος 2012 22:27

Αυτό που πας να κάνεις με το χέρι θα έλεγα ότι είναι προτιμότερο να το κάνει η database όπως πρότεινε και ο Rapid-eraser. Ξέρει να το κάνει πολύ γρηγορότερα, αρκεί να της δώσεις τα στοιχεία. Τα php loops ακόμα και για το γέμισμα του table θα τα ξέχναγα εντελώς (ειδικά αν το xml είναι - ή μπορείς να το φέρεις - σε μορφή κατάλληλη για να χρησιμοποιήσεις το xml_load.

Θα έλεγα λοιπόν να έχεις ένα temporary table με τα πεδία που έχει το xml και όταν φορτώνεις το xml να ρίχνεις εκεί όλα τα entries χωρίς έλεγχο. Το μόνο θα μπορούσε να έχει το table είναι ένας index πάνω στον αριθμό κάρτας (αν τσεκάρεις ότι υπάρχει όφελος στους χρόνους).

Αφού λοιπόν φορτώσεις αυτό τον προσωρινό πίνακα μετά με ένα query κάνεις update τον κανονικό σου πίνακα με τους πόντους από τον προσωρινό.

Οταν τελειώσεις αδειάζεις τον προσωρινό πίνακα.

Θα πρότεινα πάντως να κρατήσεις 2-3 διαφορετικές εκδοχές για να μπορείς να τσεκάρεις χρόνους και resource load σε αυτό που έχεις κάνει τώρα, αυτό που προτείνει ο rapid με indexes, χωρίς indexes.

alou
Script Master
Δημοσιεύσεις: 1374
Εγγραφή: 24 Αύγ 2007 19:52
Επικοινωνία:

While μέσα σε while υπάρχει πιο σωστός τρόπος;

Δημοσίευση από alou » 29 Μάιος 2012 23:19

Thanks για τα tips guys, ναι dva_dev θα κοιτάξω τα ενδεχόμενα και βέβαια θα επανέλθω με συμπεράσματα.

Σχετικά με foreign keys, σε mysql που δεν υποστηρίζει innodb μπορώ να κάνω κάτι (εκτός από το να το τεστάρω αλλού και αν αξίζει να γίνει αναβάθμιση :P)

Το xml δεν το ελέγχω, το παίρνω έτοιμο.

Ευχαριστώ και πάλι!

Άβαταρ μέλους
dva_dev
Script Master
Δημοσιεύσεις: 3790
Εγγραφή: 16 Σεπ 2005 01:32
Επικοινωνία:

While μέσα σε while υπάρχει πιο σωστός τρόπος;

Δημοσίευση από dva_dev » 30 Μάιος 2012 02:59

Ακόμα και χωρίς foreign keys μπορείς να ζήσεις. Ισως δεν μπορείς να έχεις ικανοποιητική απόδοση στο update χωρίς κάποιον index στον προσωρινό πίνακα πάνω στον αριθμό κάρτας. Η δοκιμή θα δείξει στην πράξη τι παίζει.

Το xml το παίρνεις έτοιμο, αλλά αν το διαβάσεις σαν text με global replace ίσως μπορείς να το φέρεις ακριβώς στα μέτρα όπως το θέλει η mysql για να το φορτώσει στον προσωρινό πίνακα.
Αν σε δυσκολεύει θα μπορούσες να πας και ανάποδα να φτιάξεις τον πίνακα έτσι ώστε να ταιριάζει με το xml (ή κάτι ενδιάμεσο, λίγο να παίξεις με τον πίνακα, λίγο με replace στο xml) ώστε να γίνει η δουλειά.

Άβαταρ μέλους
Rapid-eraser
WebDev Moderator
Δημοσιεύσεις: 6851
Εγγραφή: 05 Απρ 2003 17:50
Τοποθεσία: Πειραιάς
Επικοινωνία:

While μέσα σε while υπάρχει πιο σωστός τρόπος;

Δημοσίευση από Rapid-eraser » 30 Μάιος 2012 09:35

Από δικές μου δοκιμές είχα καταλήξει παλιότερα πως το ιδανικό είναι να γεμίζεις το query του insert στο buffer size του mysql driver που χρησιμοποιήσεις.
Κάνοντας το parse από το xml και μαζεύοντας σε ένα εσωτερικό buffer τα data να στέλνει inserts 100-100 πχ (μπορείς σε 1 insert query να περάσεις πολλά rows ταυτόχρονα).

Όσο για τα foreign keys και εγώ είμαι της άποψης ότι μπορείς να ζήσεις χωρίς αυτά, απλά τα ανέφερα για τι σε πιο σύνθετες καταστάσεις είναι μονόδρομος.
Cu, Rapid-eraser, Tα αγαθά copies κτώνται.
Love is like oxygen, You get too much you get too high
Not enough and you're gonna die, Love gets you high

alou
Script Master
Δημοσιεύσεις: 1374
Εγγραφή: 24 Αύγ 2007 19:52
Επικοινωνία:

While μέσα σε while υπάρχει πιο σωστός τρόπος;

Δημοσίευση από alou » 30 Μάιος 2012 18:38

ΟΚ άλλαξα τελείως την προσέγγιση με αυτά που μου είπατε, ακόμα το ψάχνω αλλά ήδη οι διαφορές είναι σημαντικές.

Αποφάσισα να μην είναι temp ο πίνακας που θα γράψω στη βάση από το xml ώστε να είναι διαθέσιμοι οι πόντοι και κατά την εγγραφή κάποιου (πρίν έπρεπε να γραφτεί και μετά να γίνει το πρώτο update για να δει πόντους) οπότε το όλο θέμα ήταν να 'κομματιάσω' το xml και να κάνω όσο το δυνατόν πιο efficient queries για να φτιαχτεί το table, είμαι σε μια τέτοια κατάσταση τώρα:

Κώδικας: Επιλογή όλων

//prwta truncate το νέο table
//$ptsUsed ειναι τα xml data
	
	$xmlRecords = count&#40;$ptsUsed&#41;;
	
	$eachQuery = 500; //rows per qery - to ekana se var gia na paiksw kai na dw diafores
	$lastQuery = $xmlRecords % $eachQuery; //rows for last query
	$querySets = intval&#40;$xmlRecords / $eachQuery + 1&#41;; //total queries
	
	$xmlToSql = array&#40;&#41;;
	$offset = 0; 	
	
	for &#40; $q = 1; $q <= $querySets; $q++ &#41; &#123;
		$xmlToSql = "";
		if &#40;$offset > &#40;$eachQuery * &#40;$querySets - 1&#41; -1&#41; &#41; &#123; //if last query
			for &#40; $l = 0; $l < $lastQuery; $l++ &#41; &#123;
//oli i ousia einai edw, pou ftiaxnw ena array me to query apo ta xml data kai meta to kanw implode gia na ginei ena query ana xxx &#40;$eachQuery&#41; eggrafes
    			$xmlToSql&#91;&#93; = '&#40;"'.$ptsUsed&#91;$l+$offset&#93;->PO_CardNumber.'", '.$ptsUsed&#91;$l+$offset&#93;->PO_Points.'&#41;';
			&#125;
		&#125; else &#123;
			for &#40; $i = 1; $i <= $eachQuery; $i++ &#41; &#123;
				
    			$xmlToSql&#91;&#93; = '&#40;"'.$ptsUsed&#91;$i+$offset&#93;->PO_CardNumber.'", '.$ptsUsed&#91;$i+$offset&#93;->PO_Points.'&#41;';
			&#125;
		&#125;
//implode το array που έφτιαξα παραπάνω για το query και insert
	mysql_query&#40;'INSERT INTO ... VALUES '.implode&#40;',', $xmlToSql&#41;&#41; or die&#40;'problem inserting card data from xml'&#41;;
	echo "query number ".$q." inserted<br />";
	
	$offset += $eachQuery;
	&#125;

Μετά κάνω ένα update card points από το καινούργιο table στο παλιό με κοινό στοιχείο τον αριθμό κάρτας.

Παιδιά ευχαριστώ για τα tips ξανά - μανά, φαντάζομαι κάτι τέτοιο εννοούσατε αν υπάρχει άλλο σχόλιο φυσικά μου λέτε και το ψάχνω όσο μπορώ.

Απάντηση

Επιστροφή στο “PHP Προγραμματισμός”

Μέλη σε σύνδεση

Μέλη σε αυτήν τη Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 0 επισκέπτες