development

PDO :: fetchAll 대 PDO :: fetch in a loop

big-blog 2020. 11. 8. 10:29
반응형

PDO :: fetchAll 대 PDO :: fetch in a loop


간단한 질문입니다.

루프에서 PDO :: fetchAll ()과 PDO :: fetch ()를 사용하는 것 사이에 성능 차이가 있습니까 (큰 결과 집합의 경우)?

차이가 있다면 사용자 정의 클래스의 개체를 가져오고 있습니다.

나의 초기 무식한 가정은 PDO가 하나의 명령문에서 여러 작업을 수행 할 수있는 반면 mysql_query는 하나만 실행할 수 있기 때문에 fetchAll이 더 빠를 수 있다는 것입니다. 그러나 나는 PDO의 내부 작동에 대한 지식이 거의 없으며 문서에는 이것에 대해 아무것도 말하지 않으며 fetchAll ()이 단순히 배열에 덤프 된 PHP 측 루프인지 여부는 없습니다.

도움이 필요하세요?


20 만 개의 임의 레코드가있는 작은 벤치 마크. 예상대로 fetchAll 메서드는 더 빠르지 만 더 많은 메모리가 필요합니다.

Result :
fetchAll : 0.35965991020203s, 100249408b
fetch : 0.39197015762329s, 440b

사용 된 벤치 마크 코드 :

<?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/>';

내가 거의 항상 사실임을 알게 된 PHP에 대한 한 가지 사실은 사용자가 직접 구현하는 함수가 PHP에 상응하는 것보다 거의 항상 느리다는 것입니다. 이것은 어떤 것이 PHP로 구현 될 때 C가 (PHP가 작성된) 컴파일 시간 최적화를 모두 갖지 않고 PHP 함수 호출의 높은 오버 헤드가 있기 때문입니다.


@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()){}

기억의 차이는 무시할 수 있어야합니다


"메모리 풋 프린트"를 측정하는 위의 모든 벤치 마크는 매우 단순한 이유 때문에 실제로 올바르지 않습니다.

기본적으로 PDO는 모든 것을 메모리에로드하며 fetch 또는 fetchAll을 사용하는지 상관하지 않습니다. 버퍼링되지 않은 쿼리의 이점을 실제로 얻으려면 버퍼링되지 않은 쿼리를 사용하도록 PDO에 지시해야합니다.

$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

이 경우 스크립트의 메모리 사용량에 큰 차이가 있습니다.


As Mihai Stancu was saying, there is almost no memory difference though fetchAll beats fetch + while.

Result : 
fetchAll : 0.160676956177s, 118539304b
fetch : 0.121752023697s, 118544392b

I got the results above with running while correctly:

$i = 0;
while($data[$i++] = $stmt->fetch()){
    //
}

So the fetchAll consumes less memory, but fetch + while is faster! :)


But surely if you're storing the fetched data in an array, the memory usage will be equal?

<?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

I know this is an old topic, but I run across this having the same question. Having run my own simple "benchmark" and reading what others wrote here I came to the conclusion that this is not an exact science and while one should strive to write the quality, light code, there is no point wasting too much time at the start of the project.

My suggestion is: Gather data by running the code(in beta?) for a while and then start optimizing.

In my simple benchmark (only tested execution time) I've got results varying between 5% and 50% BOTH ways. I run both options in the same script, but when I run fetch + while first it has been faster than fetchall and vice versa. (I know I should have run them single and couple hundred times get the median and mean and then compare, but - as I have said at the begining - I concluded that in my case it is too early to start doing so.)

참고URL : https://stackoverflow.com/questions/2770630/pdofetchall-vs-pdofetch-in-a-loop

반응형