PDO:: fetchAll vs. PDO:: 루프에서의 fetch
간단한 질문 하나 할게요.
루프에서 PDO::fetchAll()과 PDO::fetch()를 사용하는 것(대규모 결과 집합의 경우)에 성능 차이가 있습니까?
사용자 정의 클래스의 개체를 가져오고 있습니다(차이가 있다면).
처음에는 petchAll이 더 빠를 수 있다고 생각했지만 PDO는 하나의 문으로 여러 작업을 수행할 수 있지만 mysql_query는 하나만 실행할 수 있기 때문입니다.그러나 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 함수 호출의 오버헤드가 높기 때문입니다.
위의 모든 벤치마크는 매우 간단한 이유로 "메모리 풋프린트"를 측정하는 것이 실제로는 올바르지 않습니다.
PDO는 기본적으로 모든 것을 메모리에 로드하며 fetchAll을 사용하든 상관 없습니다.버퍼링되지 않은 쿼리를 실제로 사용하려면 PDO에 버퍼링되지 않은 쿼리를 사용하도록 지시해야 합니다.
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
이 경우 스크립트의 메모리 사용량에 큰 차이가 있습니다.
@아크
// $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()){}
메모리 차이는 부정할 수 있습니다.
Mihai Stancu가 말했듯이 fetchAll beats fetch + while을 사용해도 메모리 차이는 거의 없습니다.
Result :
fetchAll : 0.160676956177s, 118539304b
fetch : 0.121752023697s, 118544392b
올바른 실행 중 위의 결과를 얻었습니다.
$i = 0;
while($data[$i++] = $stmt->fetch()){
//
}
따라서 fetch All은 메모리를 적게 소비하지만 fetch + while이 더 빠릅니다. : )
그러나 가져온 데이터를 어레이에 저장하는 경우 메모리 사용량은 동일합니까?
<?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
이게 오래된 주제인 건 알지만, 같은 질문을 하면서 우연히 이걸 발견했어요.저만의 간단한 '벤치마크'를 실행하고 다른 사람이 쓴 글을 읽으면서 이것은 정확한 과학이 아니며 품질과 광코드를 작성하기 위해 노력해야 하지만 프로젝트를 시작할 때 너무 많은 시간을 낭비할 필요는 없다는 결론에 도달했습니다.
잠시 코드(베타?)를 실행하여 데이터를 수집한 후 최적화를 시작하는 것이 좋습니다.
간단한 벤치마크(테스트된 실행 시간만)에서는 양쪽 모두 결과가 5%에서 50%까지 다양합니다.두 옵션을 모두 같은 스크립트로 실행하지만 fetch+를 실행하면 fetchall보다 빠르며 그 반대도 마찬가지입니다.(단독으로 실행하고 수백 번 중앙값과 평균을 구해서 비교해야 한다는 것을 알지만, 처음부터 말했듯이 제 경우 그렇게 하기에는 너무 이르다는 결론을 내렸습니다.)
언급URL : https://stackoverflow.com/questions/2770630/pdofetchall-vs-pdofetch-in-a-loop
'source' 카테고리의 다른 글
Angular 5의 URL에서 쿼리 파라미터를 얻는 방법 (0) | 2023.02.09 |
---|---|
JSON JQ(기타 없는 경우) (0) | 2023.02.09 |
PDO: MySQL 서버가 사라졌습니다. (0) | 2023.02.01 |
Express를 사용하여 NodeJS 서버에서 파일 다운로드 (0) | 2023.02.01 |
어떻게 mysql에서 같은 테이블에 두 번 앉지? (0) | 2023.02.01 |