Waarom is ADODB bij mij sneller dan PDO?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Maarten Baars

Maarten Baars

18/06/2021 12:04:02
Quote Anchor link
Hallo all!

Ben bezig voor een bedrijf die een oude PHP applicatie heeft. Ik bouw dat ding zo goed als helemaal om, omdat het nogal veel spaghetticode bevat. Dat lukt aardig, maar nu zag ik dus ook dat bij het opvragen van data uit de database het oude ADODB wordt gebruikt. Dus ik dacht, ik ga daar PDO van maken, want ik lees overal dat dit sneller is.

Dat test ik dan gelijk op een van de zwaarste requests in de applicatie en wat schetst mijn verbazing: ADODB is 2 seconden sneller dan als ik die query via PDO uitvoer. Huh?! Logischerwijs moet er iets zijn wat ik mis dus ik vraag nu, kunnen jullie mij hints geven waar ik naar moet zoeken?

Hieronder een snel voorbeeld van mij om een array op te vragen via PDO. Dat komt omdat de hele app vol zit met iterations over een array dus ik dacht, ik start dan maar eerst met een array.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
$dsn = "mysql:host=". MYSQL_HOST . ";dbname=" . MYSQL_DB . ";port=" . MYSQL_PORT . "charset=" . MYSQL_CHARSET;

try {
    $pdo = new PDO($dsn, MYSQL_USER, MYSQL_PASS, $options);
} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

$statement = $pdo->query($sql);
return ($statement !== false ? $statement : null);


De oude ADODB code doet dit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$rs = WAFDB::getConnection()->Execute($sql_listing);


Een array maken wordt op deze manier gedaan:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
$this->_recordcount = $rs->RecordCount();
$this->found_rows();
while (!$rs->EOF) {
    $arr[$rs->fields[$this->pKey]] = $rs->fields;
    $rs->moveNext();
}


Je ziet een extra "RecordCount" en dan ook nog een "found_rows()" call. Dus er worden extra queries uitgevoerd, vervolgens wordt er een array gemaakt door over het huidige resultaat te iteraten, en vervolgens ergens anders in de code wordt er over die array geitereerd om het resultaat weer te geven. 3 tot 4x teveel over het resultaat heen, teveel queries etcetera. Je snapt mijn verbazing dat als ik dat allemaal niet doe en het via PDO doe het ineens langer duurt.

Bedankt voor de hulp.

Groet
Maarten
Gewijzigd op 18/06/2021 12:05:04 door Maarten Baars
 
PHP hulp

PHP hulp

18/09/2021 13:29:03
 
Thom nvt

Thom nvt

18/06/2021 13:14:50
Quote Anchor link
Hoe ben je tot die getallen gekomen?

Ik zou eens een Profiler (XDebug bijv.) loslaten op je applicatie, die splitst netjes per functie-call en classname uit hoe veel tijd er in gaat zitten, vanaf daar kun je gaan analyseren of het écht in PDO zit of dat je onbedoeld iets doet wat niet bijster efficiënt is.
 
Maarten Baars

Maarten Baars

18/06/2021 14:48:23
Quote Anchor link
Hey Thom

Bedankt voor je input. Laat ik voor het gemak het proces eens versimpelen:

ADODB->query => Itereren over resultaat => berekeningen doen => toon uitkomst (9 seconden)

Jouw idee is, wellicht kan de tijd gaan zitten in dat itereren over het resultaat en/of de berekeningen. Feitelijk heb je ook gelijk, want daarin worden nóg meer queries uitgevoerd en de applicatie waar ik aan werk zit vol met spaghetti. Maar als ik 1 element in dat proces aanpas, namelijk we gebruiken PDO, dan zou je zeggen dat stap 1 sneller zou moeten gaan en je dus in ieder geval:
A. Quitte speelt
óf
B. Snelheidswinst krijgt

PDO->query => Itereren over resultaat => berekeningen doen => toon resultaat (11 seconden)

Verbazing alom dus. Want hoe kan het, ookal is de code shit, dat mét PDO hetzelfde proces langer duurt dan anders? Het resultaat van de query is namelijk exact hetzelfde opgebouwd (array). Sterker nog, de code die met ADODB de data ophaalde deed tenminste nog 1 extra iteratie over de gehele resultatenset om zo een aangepaste array te maken waarbij de Primary key als array key werd ingesteld. Een totaal onnodige actie waarvan ik dacht megaveel snelheidswinst te kunnen pakken. Want met de PDO versie haal ik gewoon data op en geef die zonder dat extra gedoe terug.

De snelheidsdata is verkregen door in Firefox de debugdata op te halen met F12.

Dank

Maarten
Gewijzigd op 18/06/2021 14:51:01 door Maarten Baars
 
Ad Fundum

Ad Fundum

19/06/2021 10:43:47
Quote Anchor link
Wat je moet weten is of ADODB en PDO allebei wel dezelfde query naar de database sturen. Je kunt daarvoor ADBDO en PDO debuggen of SQL logging in de database aanzetten.

Als beide queries hetzelfde zijn, ligt de 2 seconden vertraging in de I/O met de database driver. Dat kan verklaard worden door een verschil in instellingen, bijvoorbeeld: query je wel op hetzelfde schema, maakt de ene gebruik van TLS en de andere niet, staan de instellingen voor encoding goed of wordt alle I/O getranscodeerd?

Als er een verschil zit op de queries moet je daar goed naar kijken. Verschil in prestaties kan verklaard worden door net even anders groeperen of nesten van queries tot domweg onhandig of geen gebruik maken van indices. Je krijgt het boven water met de SQL keywords EXPLAIN en ANALYSE.
 
Thom nvt

Thom nvt

19/06/2021 17:41:32
Quote Anchor link
Maarten Baars op 18/06/2021 14:48:23:
PDO->query => Itereren over resultaat => berekeningen doen => toon resultaat (11 seconden)

Verbazing alom dus. Want hoe kan het, ookal is de code shit, dat mét PDO hetzelfde proces langer duurt dan anders?

...

De snelheidsdata is verkregen door in Firefox de debugdata op te halen met F12.


Dat is niet echt een goede test om enkel de duur van de DB query te vergelijken.
Je introduceert namelijk nogal wat overhead in de vorm van een HTTP(S) request en het opzetten van de database connectie en alle overige code in je applicatie.
Het zou best kunnen dat het optuigen van een PDO connectie en bijbehorende classes langer duurt dan bij ADODB, die overhead zit er nu ook in.

Ik zou toch eens een profiler zoals XDebug loslaten op je applicatie, of in ieder geval alleen de duur van alleen de query meten d.m.v. microtime.
Iets als onderstaand dus:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
$start
= microtime(true);
// PDO->query hier
$end = microtime(true);
$duratie = $end - $start; // Resultaat is in microseconden.
?>


Meten is weten en hoe specifieker je je meting maakt hoe beter je weet waar het verschil vandaan komt.
Gewijzigd op 19/06/2021 17:41:59 door Thom nvt
 
John D

John D

20/06/2021 22:33:16
Quote Anchor link
Maarten Baars op 18/06/2021 12:04:02:
nu zag ik dus ook dat bij het opvragen van data uit de database het oude ADODB wordt gebruikt. Dus ik dacht, ik ga daar PDO van maken, want ik lees overal dat dit sneller is.

Met "oude ADODB" doe je ADODB te kort, er is een recente 2021 release beschikbaar als je na de testen toch besluit om met ADODB door te gaan. Het is zinvol om de test die Thom aanraadt uit te voeren. Daarnaast is het zinvol om je query's ook te beoordelen. Waarom na het ophalen van data nog itereren in PHP? Is de query niet slimmer te maken die het itereren overbodig maakt?
Gewijzigd op 20/06/2021 22:37:11 door John D
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.