MySQL tárolt eljárások extrém mennyiségben
Sziasztok!
Nagy mennyiségű adatot kell importálnom MySQL adatbázisba, úgy, hogy közben egy keveset számolgatnom is kell. Az adatbázis konzisztencia szempontjából azt a megoldást választottam, hogy a bemenő adatokat MySQL tárolt eljárások kapják meg, azok kiszámolnak, ellenőriznek mindent, majd Insertálják a megfelelő táblákba az adatokat.
Egy ilyen lefutása kb 0.0002s a PHPmyadmin szerint.
A probléma ott kezdődik, hogy százezres nagyságrendben kellene lefuttatnom ezt a tárolt eljárást. ( Mivel ez egy inicializációs művelet, ezért nem probléma, ha perceket vesz igénybe, csak fusson le.)
PHP-val hívom meg a Mysqli->multiple_query() -t. 100 asával adom be a hívásokat. ( 5000 nél már kiakadt) A PHP-val folyamatosan kijelzem a belső állapotot, minden sikeres ilyen 100as hívás után újabb jelzést küld a php a böngészőnek (Flush()) így látom, hogy hol tart a folyamat. Ez így szép is lenne, de a tapasztalat az, hogy valamiért egyre lassul a rendszer. Az elején simán 1s alatt van egy ilyen multiple_query-nek a lefutása, de úgy 5-10000 hívás után már közeledik a 1,5-2 s-hez és egyre lassul.
A kérdés konkrétan: tud valaki segíteni abban, hogy mit tehetnék? valamilyen változókat kéne felszabadítanom, vagy mi lassíthatja az SQL szervert?
Kérlek segítsetek!
■ Nagy mennyiségű adatot kell importálnom MySQL adatbázisba, úgy, hogy közben egy keveset számolgatnom is kell. Az adatbázis konzisztencia szempontjából azt a megoldást választottam, hogy a bemenő adatokat MySQL tárolt eljárások kapják meg, azok kiszámolnak, ellenőriznek mindent, majd Insertálják a megfelelő táblákba az adatokat.
Egy ilyen lefutása kb 0.0002s a PHPmyadmin szerint.
A probléma ott kezdődik, hogy százezres nagyságrendben kellene lefuttatnom ezt a tárolt eljárást. ( Mivel ez egy inicializációs művelet, ezért nem probléma, ha perceket vesz igénybe, csak fusson le.)
PHP-val hívom meg a Mysqli->multiple_query() -t. 100 asával adom be a hívásokat. ( 5000 nél már kiakadt) A PHP-val folyamatosan kijelzem a belső állapotot, minden sikeres ilyen 100as hívás után újabb jelzést küld a php a böngészőnek (Flush()) így látom, hogy hol tart a folyamat. Ez így szép is lenne, de a tapasztalat az, hogy valamiért egyre lassul a rendszer. Az elején simán 1s alatt van egy ilyen multiple_query-nek a lefutása, de úgy 5-10000 hívás után már közeledik a 1,5-2 s-hez és egyre lassul.
A kérdés konkrétan: tud valaki segíteni abban, hogy mit tehetnék? valamilyen változókat kéne felszabadítanom, vagy mi lassíthatja az SQL szervert?
Kérlek segítsetek!
Surun fut?
Igazabol en nem hiszem hogy kinlodnek a helyedben tarolt eljarasokkal. Egesz nyugodtan csinalhatod PHP-bol az egeszet. En ilyen esetekben mindig irok egy scriptet ami tablankent kb atemeli a sorokat kotegelt INSERT-ekkel. Valamint a vegen soronkent ellenorzi az adatokat hogy minden atjott-e rendesen.
A lassulas pedig gondolom abbol ered hogy egyszeruen tobb adat van a tablakban.
Ha jol ertem itt valami olyasmirol lehet szo, hogy valaki egy admin szeru feluleten feltolt valamilyen filet (csv, vagy xls, vagy barmi), te pedig importalod azt az adatbazisba.
Ilyenkor ha nem nagyon muszaj a kozvetlen visszajelzes a usernek a muvelet allapotarol, en mindenkeppen kulon kezelnem a feltoltest es az importalast.
Ertem ezalatt hogy csinalsz egy queue tablat amibe bekerul a feltoltes-rol egy esemeny (importalasrol egy feladat), es azt egy cronbol vagy vegetelenul futtatott script felnyalabolja, es elvegzi a muveletet.
Aztan ha lefutott akkor visszaertesiti a usert. Bar ha megis kell kozvetlen "process bar", az is egyszeruen megoldhato ha az adott importalas neha beertesiti a queue tablaba hogy hol tart.
Nem
Lassulás:
Nem hiszem, hogy az adatok mennyisége miatt lassulna. Nagy mennyiségű adat összesen 2 táblában keletkezik, de ezekbe kizárólag insertálok. A Insert időigénye drasztikusan nő, ha párezer sor már van a táblában??
Valóban CSV ből importálom az adatokat, de tényleg megéri php-val csinálni? ugyanis minden sor importálásához 3-4 dolgot ellenőrizni kell az adatbázisban, azaz legalább 2-3 adatbázis elérést kell csinálni soronként.
Jelen helyzet:
Módosítottam a tárolt eljárásom, egy kis optimalizálás, illetve egy nagyobb számolási igényű művelet kihagyása mellett jelentősen gyorsult a folyamat, most ~1 perc alatt végbe megy az importálás, de még mindig jelentős a lassulás a folyamat végére. ( a kihagyott számítást meg utólag, egy trigger hajtja végre úgy tovább 2 perc alatt. Így szumma 3 perc alatt kész minden, eddig meg 15 perc alatt sem jutott a végére)
Továbbra is várom az ötleteket a lassulással kapcsolatban.
memoria?
Kapcsold ki az indexet a
InnoDB vs. MyISAM
LOAD DATA?
http://dev.mysql.com/doc/refman/5.1/en/load-data.html
raadasul fentebb emlitette a
sajat tesztek alapjan ez a leggyorsabb import folyamat.
ha valami miatt megsem lehet CSV-bol tolni (egyik insert eredmenyet egy masik insertnek kell felhasznalnia mondjuk), akkor a leggyorsabb megoldas az az, hogy egy tranzakcioba megy az egesz, kotegelt insertekkel.
igy csak a tranzakcio vegen a commitnal lesznek ujraszamolva a tablan levo indexek, nem pedig minden beszuraskor.
viszont itt vigyazni kell arra, hogy az ilyen nagymeretu tranzakciok nem tesznek jot a replikacios lag-nak(mivel mysql-ben a replikacio szerializalva 1 szalon tortenik), ha replikalt kornyezetben kell importalni, akkor inkabb a teljes import legyen lassabb (erts: kissebb tranzakciok, gyakoribb commit, osszessegeben tovabb tart az import), de ne nyomja fel a replikacios lagot.
Tyrael