Az adatbáziskezelő dolga a megfelelő algoritmus kiválasztása, a lekérdezés, az érintett táblák mérete, statisztikák, stb figyelembe vételével. Persze ha ez nem elégséges, akkor manuálisan felül lehet bírálni (hint), pl Oracle, illetve MSSQL tud ilyeneket. Ahogy néztem, a MySQL egyedül a nested loop join algoritmust támogatja.
A blogmarkot leginkább érdekességnek szántam, betekintést nyújt az adatbáziskezelők lelki világába, adott esetben könnyebben meg tudjuk érteni, miért lehet is olyan lassú egy-egy lekérdezés.
Ha már itt tartunk ti használtátok már a phpunit/dbunit-ot integrációs tesztekhez? A fixture felállítása valami baromi lassú, 1.5 sec néhány táblán a cascade truncate és a teszt adatok feltöltése. Azért ez elég durva... (és alapból minden teszt előtt megcsinálja)
Jelenleg node.js-ben dolgozok, teszteknél (itt leginkább unit tesztekről van szó) mindig próbálok mockolni (hálózat, adatbázis, fájlrendszer, stb). Egy integrációs tesztnél szerintem nem probléma a sebesség, hiszen azt ritkábban kell lefuttatni.
Persze, de azért ez nem egy olyan hűde bonyolult milliárd rekordos erőforrás igényes valami, hogy ennyi idő alatt csinálja meg. Van összesen 8 tábla meg 15 sor, amit fel kéne tennie... Valami nagy gebasz lehet a phpunit/dbunit kódjában, de időm sajnos nincs megnézni. Majd teszek be query loggolós PDO-t, meg xdebug-ot, aztán megnézem, de az sem ebben a hónapban lesz...
Tapasztalataim szerint ilyen méretű sebesség problémákat mindig IO -ra lehet visszavezetni. Ha van rá mód érdemes lehet kipróbálni pár ilyen tesztet in memory sqlite adatbázisokkal ezt a feltételezést igazolandó. Legtöbb adatbázisrendszer truncate utasítások után megvárja hogy fájlrendszer ki-syncelje lemezre az adatokat és ezért borzalmasan lassúak többi bufferelt művelethez képest. (pl sql delete sokkal gyorsabb mysql alatt mint truncate)
Ha linuxon + ext3-4 pároson ül a db megpróbálhatod kikapcsolni a barriereket az mounton amin a db fájlok vannak (nyilván észben tartva a dolog veszélyeit), ez nálam 10x körüli gyorsulást hozott db nehéz testsuite-oknál.
Hát mysql-hez írták, hogy mit kell, ott is fájlba mentésről volt szó, meg log fájlokról, meg ilyen marhaságokról. A pgsql-nél nem vágom hogyan lehetne orvosolni... A cascade truncate meg a foreign key-ek miatt kell. A másik lehetőség, hogy deferrable-ra rakom a kulcsokat, és tranzakcióba teszek mindent, viszont a dbunit-ba nem szívesen írok bele, hogy truncate helyett sima delete-et használjon. Jobb lenne inkább így megjavítani valahogy. A mysql-ben az innodb_flush_log_at_trx_commit = 2 beállítással csinálják...
Én inkább globális fixture-t használok + minden teszt végén rollback. Kevésbé karbantartható, és kicsit kevésbé megbízható is, de sokkal-sokkal gyorsabb.
Teszt elején tranzakciót nyitsz, teszt végén rollbackeled, és átírod a használt keretrendszer tranzakciókezelését, hogy teszt módban ne csináljon semmit. Van egy csomó buktatója (MyISAM táblák, TRUNCATE és egyéb tranzakció-törő műveletek, olyan funkcionalitás, ahol a tranzakciókezelés nem transzparens, mert pl az üzleti logika bizonyos esetekben kiad egy rollbacket, és utána végez még adatbázisműveleteket), de a gyakorlatban ezek elég ritkán fordulnak elő; másrészt ugyanolyan gyors vagy még gyorsabb, mint a tesztelt funkciónak az éles működése, akár párhuzamosan sok tesztet is futtathatsz ugyanazon az adatbázison, és a fixture-öket csak egyszer az egész teszt suite legelején kell futtatni (vagy akár még akkor se, ha tudod valahogy figyelni, hogy mikor változnak a fájlok).
Ha a fájlokat db-ben tárolod, akkor erre sincs szükség. Ja okos. pgsql-ben vannak savepoint-ok a tranzakciókon belül, úgyhogy még egyszerűbb megcsinálni vele... Azt hiszem én is ezt fogom csinálni... Annyi a gond vele, hogy pgsql-ben a fk constrainteknél be lehet állítani, hogy deferrable, ami olyan, hogy a commit-nál ellenőrzi csak. Pl a törlés vagy a hozzáadás sokkal egyszerűbb vele, mert tetszőleges sorrendben meg lehet csinálni. Na az ilyen megoldásokat kilövi a rollback-es módszer. Mysql-hez elhiszem, hogy jó, pgsql-nél viszont el kell gondolkodni, hogy megéri e...
Hol érdemes/lehet ilyet
Az adatbáziskezelő dolga a
A blogmarkot leginkább érdekességnek szántam, betekintést nyújt az adatbáziskezelők lelki világába, adott esetben könnyebben meg tudjuk érteni, miért lehet is olyan lassú egy-egy lekérdezés.
Ha már itt tartunk ti
Jelenleg node.js-ben
Persze, de azért ez nem egy
IO
Ha linuxon + ext3-4 pároson ül a db megpróbálhatod kikapcsolni a barriereket az mounton amin a db fájlok vannak (nyilván észben tartva a dolog veszélyeit), ez nálam 10x körüli gyorsulást hozott db nehéz testsuite-oknál.
Hát mysql-hez írták, hogy mit
innodb_flush_log_at_trx_commit = 2
beállítással csinálják...Én inkább globális fixture-t
Ezt a minden teszt végén
Teszt elején tranzakciót
Ha a fájlokat db-ben tárolod,