Nur eine kurze Frage.
Gibt es einen Leistungsunterschied zwischen der Verwendung von PDO :: fetchAll () und PDO :: fetch () in einer Schleife (für große Ergebnismengen)?
Ich rufe in Objekte einer benutzerdefinierten Klasse, wenn das einen Unterschied macht.
Meine anfängliche ungebildete Annahme war, dass fetchAll möglicherweise schneller ist, da PDO mehrere Operationen in einer Anweisung ausführen kann, während mysql_query nur eine ausführen kann. Ich habe jedoch wenig Wissen über das Innenleben von PDO und die Dokumentation sagt nichts darüber aus und ob fetchAll () einfach eine PHP-seitige Schleife ist, die in ein Array geschrieben wird.
Irgendeine Hilfe?
Antworten:
Kleiner Benchmark mit 200.000 zufälligen Datensätzen. Wie erwartet ist die fetchAll-Methode schneller, benötigt jedoch mehr Speicher.
Result : fetchAll : 0.35965991020203s, 100249408b fetch : 0.39197015762329s, 440b
Der verwendete Benchmark-Code:
<?php // First benchmark : speed $dbh = new PDO('mysql:dbname=testage;dbhost=localhost', 'root', ''); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = 'SELECT * FROM test_table WHERE 1'; $stmt = $dbh->query($sql); $data = array(); $start_all = microtime(true); $data = $stmt->fetchAll(); $end_all = microtime(true); $stmt = $dbh->query($sql); $data = array(); $start_one = microtime(true); while($data = $stmt->fetch()){} $end_one = microtime(true); // Second benchmark : memory usage $stmt = $dbh->query($sql); $data = array(); $memory_start_all = memory_get_usage(); $data = $stmt->fetchAll(); $memory_end_all = memory_get_usage(); $stmt = $dbh->query($sql); $data = array(); $memory_end_one = 0; $memory_start_one = memory_get_usage(); while($data = $stmt->fetch()){ $memory_end_one = max($memory_end_one, memory_get_usage()); } echo 'Result : <br/> fetchAll : ' . ($end_all - $start_all) . 's, ' . ($memory_end_all - $memory_start_all) . 'b<br/> fetch : ' . ($end_one - $start_one) . 's, ' . ($memory_end_one - $memory_start_one) . 'b<br/>';
quelle
memory_get_usage(/* true */)
zeigt Ihnen den von PHP selbst zugewiesenen Speicher. Es ist nicht zeigen Ihnen die BIBLIOTHEK zugewiesenen Speicher. Libmysqlclient und mysqlnd verwenden ihren eigenen Speicher. Nicht der Speicher von PHP.memory_get*usage()
nur den von PHP gesteuerten Speicher an. Direkte Aufrufe von malloc () oder mmap () werden dabei nicht berücksichtigt. Und sicher, ungepufferte Abfragen lesen grundsätzlich nicht aus dem Socket. Dies bedeutet, dass die Ergebnisse dann auf der MySQL-Serverseite gepuffert werden. Aber gepufferte Abfragen werden clientseitig gespeichert… im Speicher von libmysqlclient, der über malloc () zugewiesen wird. (mysqlnd verwendet emalloc (), das Speicher über den Zend-Speicherzuweiser zuweist)… Aber dieser Benchmark wurde offensichtlich mit libmysqlclient durchgeführt. (Da Zahlen für mysqlnd zu unrealistisch sind.)Eine Sache über PHP, die ich fast immer als wahr befunden habe, ist, dass eine Funktion, die Sie selbst implementieren, fast immer langsamer ist als das PHP-Äquivalent. Dies liegt daran, dass bei der Implementierung von etwas in PHP nicht alle Optimierungen für die Kompilierungszeit von C (in die PHP geschrieben ist) vorhanden sind und der Aufwand für PHP-Funktionsaufrufe hoch ist.
quelle
sort
. @Byron Ich wette, Sie werden feststellen, dass das Abrufen aller Ergebnisse mit fetchAll () immer noch schneller ist, aber Sie können es mit einem Benchmark vergleichen,microtime(TRUE)
wenn Sie Zweifel haben.O(n log n)
- es gibt ein bisschen mehr Einsparungen zu erzielen .Alle Benchmarks, über denen der "Speicherbedarf" gemessen wird, sind aus dem sehr einfachen Grund tatsächlich falsch.
PDO lädt standardmäßig alle Dinge in den Speicher und es ist egal, ob Sie fetch oder fetchAll verwenden. Um die Vorteile einer ungepufferten Abfrage wirklich nutzen zu können, sollten Sie PDO anweisen, ungepufferte Abfragen zu verwenden:
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
In diesem Fall sehen Sie einen großen Unterschied im Speicherbedarf des Skripts
quelle
$stmt->fetch()
bei Verwendung gepufferter Abfragen (Standardeinstellung) und der Verwendung$stmt->fetch()
bei ungepufferten Abfragen (PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
Attribut festgelegt auffalse
)? Ich habe gesehen, dass selbst wenn Sie den standardmäßigen gepufferten Modus verwenden, dies$stmt->fetch()
für sehr große Datenmengen funktioniert und$stmt->fetchAll()
möglicherweise einen Speicherbeschränkungsfehler zurückgibt. Also ist$stmt->fetch()
irgendwieunbuffered
?@Arkh
// $data in this case is an array of rows; $data = $stmt->fetchAll(); // $data in this case is just one row after each loop; while($data = $stmt->fetch()){} // Try using $i = 0; while($data[$i++] = $stmt->fetch()){}
Der Speicherunterschied sollte vernachlässigbar werden
quelle
Wie Mihai Stancu sagte, gibt es fast keinen Speicherunterschied, obwohl fetchAll fetch + while schlägt.
Result : fetchAll : 0.160676956177s, 118539304b fetch : 0.121752023697s, 118544392b
Ich habe die obigen Ergebnisse mit korrektem Laufen erhalten:
$i = 0; while($data[$i++] = $stmt->fetch()){ // }
Das fetchAll verbraucht also weniger Speicher, aber fetch + while ist schneller! :) :)
quelle
fetchAll
) gegen 0,12 (fetch
)Aber wenn Sie die abgerufenen Daten in einem Array speichern, ist die Speichernutzung sicher gleich?
<?php define('DB_HOST', 'localhost'); define('DB_USER', 'root'); define('DB_PASS', ''); // database to use define('DB', 'test'); try { $dbh = new \PDO('mysql:dbname='. DB .';host='. DB_HOST, DB_USER, DB_PASS); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = 'SELECT * FROM users WHERE 1'; $stmt = $dbh->query($sql); $data = array(); $start_all = microtime(true); $data = $stmt->fetchAll(); $end_all = microtime(true); $stmt = $dbh->query($sql); $data = array(); $start_one = microtime(true); while($data = $stmt->fetch()){} $end_one = microtime(true); // Second benchmark : memory usage $stmt = $dbh->query($sql); $data = array(); $memory_start_all = memory_get_usage(); $data = $stmt->fetchAll(); $memory_end_all = memory_get_usage(); $stmt = $dbh->query($sql); $data = array(); $memory_end_one = 0; $memory_start_one = memory_get_usage(); while($data[] = $stmt->fetch()){ $memory_end_one = max($memory_end_one, memory_get_usage()); } echo 'Result : <br/> fetchAll : ' . ($end_all - $start_all) . 's, ' . ($memory_end_all - $memory_start_all) . 'b<br/> fetch : ' . ($end_one - $start_one) . 's, ' . ($memory_end_one - $memory_start_one) . 'b<br/>'; } catch ( PDOException $e ) { echo $e->getMessage(); } ?> Result : fetchAll : 2.6941299438477E-5s, 9824b fetch : 1.5974044799805E-5s, 9824b
quelle
Ich weiß, dass dies ein altes Thema ist, aber ich stoße darauf mit der gleichen Frage. Nachdem ich meinen eigenen einfachen "Benchmark" durchgeführt und gelesen hatte, was andere hier geschrieben haben, kam ich zu dem Schluss, dass dies keine exakte Wissenschaft ist, und obwohl man sich bemühen sollte, den hochwertigen, leichten Code zu schreiben, macht es keinen Sinn, zu Beginn zu viel Zeit zu verschwenden von dem Projekt.
Mein Vorschlag ist: Sammeln Sie Daten, indem Sie den Code (in der Beta?) Eine Weile ausführen und dann mit der Optimierung beginnen.
In meinem einfachen Benchmark (nur getestete Ausführungszeit) habe ich Ergebnisse, die BEIDE zwischen 5% und 50% variieren. Ich führe beide Optionen im selben Skript aus, aber wenn ich fetch + ausführe, war es zuerst schneller als fetchall und umgekehrt. (Ich weiß, ich hätte sie einzeln ausführen und ein paar hundert Mal den Median und den Mittelwert ermitteln und dann vergleichen sollen, aber - wie ich zu Beginn gesagt habe - bin ich zu dem Schluss gekommen, dass es in meinem Fall zu früh ist, damit zu beginnen.)
quelle