ugrás a tartalomhoz

Egyik adatbázisból a másikba másolás bizonyos feltételek teljesülése esetén

kotapeter · 2014. Okt. 1. (Sze), 19.00
Sziasztok!

Egy webáruházat fejlesztek és azt szeretném megoldani, hogy az offline bolt raktárkészletét folyamatosan kövesse a webáruház raktárkészlete. Kb. 3000 termékről van szó.
Tehát ha eladnak valamit az offline boltban, akkor a webáruházban is csökkenjen annak a terméknek a darabszáma.

Ezt egyelőre egy cron-al oldottam meg. Linkelem a PHP kódot, ami minden egyes percben lefutott.

<?php
	$db = new MySQLi(offline üzlet adatbázisa);
	$db2 = new MySQLi(online üzlet adatbázisa);

	if ($db->connect_errno) {
    	exit();
	}
	
	$lekerdez = "select cikkszam,cikkszam_nev,db,kisker_ar,nyilv_ar,kategoria,db from cikkszam order by 1";
	$lekerdez2 = "select model,quantity from bio_product";

	$talalat = $db->query($lekerdez);
	$talalat2 = $db2->query($lekerdez2); 
	
	$n = $talalat->num_rows;
	$s = $talalat2->num_rows;

	for ($i=0; $i<$s; $i++) {

		$sor2 = $talalat2->fetch_assoc();
		$aktdb=0;
		for ($j=0; $j<$n; $j++) {
			$sor = $talalat->fetch_assoc();
			if (stripslashes($sor['cikkszam']) == stripslashes($sor2['model']) && stripslashes($sor['db']) != stripslashes($sor2['quantity'])) {
				$aktdb = $sor['db'];
				mysqli_query($db2,"UPDATE bio_product SET quantity=".$aktdb." WHERE model='".stripslashes($sor2['model'])."'");
				break;
			}
		}
		$talalat = $db->query($lekerdez);
	}
	$db->close();
?>
Nos, ezzel az egyszerű kóddal az a legnagyobb gond, hogy 3000 termék esetén csekély 4 óra alatt fut le.
Biztos vagyok benne, hogy van ennél sokkal jobb és elegánsabb megoldás.

Ha van ötletetek kérlek osszátok meg velem!

Köszönöm!

Peti
 
1

Eseményvezérlés

Pepita · 2014. Okt. 1. (Sze), 19.10
Nem kellene összevont ciklus, hanem valamilyen eseményvezérlés, amit az offline készletező indít, ha eladás (vagy beszerzés) történik. Pl. egy külön táblába felveszi a módosított termék cikkszámát.
A crontabod így már csak ebből a táblából "válogatva" keres - néhány ms alatt és természetesen törli / frissíti ebben a táblában is a feldolgozott rekordokat.
2

Adatbázis optimalizálás

tisch.david · 2014. Okt. 1. (Sze), 21.24
Kedves Péter!

- Muszáj két külön adatbázisban lennie a két rendszernek? Egyszerűbb lenne, ha mindenki ugyanazzal a raktárkészlettel gazdálkodna.
- Ez a kód, amit írtál, csak a webshop adatbázisát igazítja az offline boltéhoz, fordítva nem frissít. Mi van, ha a webshopban adnak el? Akkor nem kéne a bolti készletet is csökkenteni? Másrészt a frissítésben a mennyiségeknél a != operátort használod. Az nem gond, ha a webshop kevesebb készletét csapod agyon a boltban nyilvántartott nagyobb értékkel?
- Ha mindenképpen ezt az utat akarod járni, akkor nem tudod megoldani, hogy a webshop adatbázisából elérhető legyen a másik adatbázis? Mert akkor sokkal hatékonyabb SQL utasítással nagyon rövid idő alatt is frissíthetnéd az online készletet.

Üdv:

Dávid
3

optimalizáció

szabo.b.gabor · 2014. Okt. 2. (Cs), 08.53
==================================
A meglévő kódot így optimalizálnám
==================================

---------------
Sztem strip_slashes felesleges db -> db adatmozgásnál, feltételezve hogy a cikkszám nem tartalmaz veszélyes karaktereket. Sztem ez teljesül, de ez a pont nem is fontos.

---------------
Két ciklusod van, mind a kettő 3000 sort tartalmaz 3000*3000 az 9 000 000 iteráció, ráadásul a $db-n 3000-szer kéred le ugyanazt :D

Szóval rendezd mind a két lekérdezésedet cikkszám szerint, és hol az egyik hol a másik rekordset-en hívd a fetch-t aszerint, hogy melyik tartalmaz kisebb értéket, ha egyezés van, akkor hajtsd végre a vizsgálatot, módosítást.

Ezt a pontot csináld, meg ettől lesz gyorsabb a történet.

---------------
Valamint csinálhatsz még prepared statementet az update-re, de amíg csak 10-20 update van, addig ezzel sem fogsz sokat nyerni.

---------------
Ja meg for ciklusok helyett inkább while(($row = $talalat->fetch()) !== false){}

====================

Amúgy érdemes volna elgondolkodni olyasmin amit Pepita mondott, esetleg valami queue-t létrehozni, amibe beledobálod a változásokat, a másik oldalon meg tárolod, hogy meddig vannak feldolgozva a változások. Ami ezt a queue-t tölti, az feltöltés után akár meg is hívhatná a másik oldal feldolgozó script-jét.

Arra is figyelned kellene, hogy ezek a script-ek ne fussanak egymásra, db lockokkal vagy akár azt biztosítani, hogy csak egy példány futhasson a feldolgozó scriptből.
4

Plusz

Hidvégi Gábor · 2014. Okt. 2. (Cs), 10.55
Talán ilyenkor legcélszerűbb egy fájlba kiírni az egészet, azon belül is egy tranzakcióba.

frissit.sql tartalma:

BEGIN;

UPDATE bio_product SET quantity=5 WHERE model=2200;
UPDATE bio_product SET quantity=0 WHERE model=3410;

COMMIT;

Aztán a végén egy parancsot kell lefuttatni:
exec('mysql -u user -p jelszo sema_neve < frissit.sql', $kimenet_tomb, $visszateresi_ertek);

Ha háromezer terméket kell frissíteni, annak elvileg pár másodperc alatt meg kell így lennie. A 'sema_neve' az "adatbázis", amiben a bio_product tábla van.

Emellett szerintem a php szintjén nem feltétlenül érdemes vizsgálni, hogy változott-e a termékek darabszáma, ugyanis az UPDATE esetén a MySQL ezt megteszi. Ha nem változik az érték, akkor azt a frissítő lekérdezést egyszerűen nem futtatja le, és elképzelhetőnek tartom, hogy ha a nyers erő módszerével egyszerűen minden sorra írnál UPDATE-et, az is gyorsítana (3000 soron egy-egy műveletet elvégezni az nem tétel az adatbáziskezelőnek).
5

DB export/import

gabesz666 · 2014. Okt. 3. (P), 09.31
Bár jóval szebb megoldást is tudnék mondani, de mint legegyszerűbb és az általad írt megoldásnál valószínűleg jóval gyorsabb eredményt lehetne elérni, ha csinálsz egy mysql dump-ot a forrás adatbázisról, dobod a cél adatbázist és beimportálod a dump-ot. Persze ez csak akkor működik, ha a két adatbázis struktúrája egy az egyben megegyezik.
6

Profibb

janoszen · 2014. Okt. 3. (P), 12.06
Ennel vannak sokkal professzionalisabb megoldasok, ugy hivjak oket, hogy ETL toolok. Ezek olyan eszkozok, amiket a BI (Business Intelligence) szektorban hasznalnak es nagy mennyisegu adatbetoltesre szolgalnak.

Ha tudsz a szerveren Java-t futtatni, nezd meg a Kettle-t, valoszinuleg sokkal jobban fog mukodni mint a kezzel irt megoldasok.
7

Kimaradt

Pepita · 2014. Okt. 3. (P), 17.05
Elsőre kifelejtettem a kétirányúságot, ami szintén fontos.
Azt is kezelned kell, ha a webshop adott el vmit.
Az is jó ötlet, hogy egy db legyen, ha lehet.

A dump mindezt kinyírja, semmiképp sem jó.
8

slave

Poetro · 2014. Okt. 3. (P), 17.26
Vagy ha nem is egy db, de legyen legalabb slave.
9

hogy?

Pepita · 2014. Okt. 3. (P), 22.39
A slave hogyan tud visszahatni a master keszletere?
10

Másolás

Poetro · 2014. Okt. 3. (P), 22.41
Az offline raktárkészletet a slave-be kellene replikálni, és akkor könnyebb lenne hozzáférni, mert egy gépen futna a kettő.