PHPとMySQLでまとめてレコード取得と小分けに取得の比較
クエリの投げる回数とその後のループ処理でどうすべきかで悩むので比較してみた。
やりたいことは「100万レコードに対して何か処理を行う」。
そのために、クエリを投げる回数と取得してくる件数の絡みでどっちが良いのかが知りたい。
試したソースは下記2種類のような感じ。
echo “MEMORY Fst: ” . number_format(memory_get_usage()) . ” byte” . “\n”;
$timeFst = microtime(true);
// 取得件数を減らして、クエリを10回投げる
$q = ‘select * from ○○○○ limit 10000;’;
for ( $i=0; $i<10; $i++ ) {
$stmt = $pdo->prepare($q);
if($stmt->execute()) {
$dataAry = new StatementIterator($stmt);
foreach ( $dataAry as $rowData) {
// print_r($rowData);
}
unset($dataAry, $stmt);
}
}
$timeEnd = microtime(true);
echo “MEMORY End: ” . number_format(memory_get_usage()) . ” byte” . “\n”;
echo “time: ” . bcsub($timeEnd, $timeFst, 5) . “\n”;
echo “MEMORY Fst: ” . number_format(memory_get_usage()) . ” byte” . “\n”;
$timeFst = microtime(true);
// 取得件数を減らさず、クエリを1回投げる
$q = ‘select * from ○○○○ limit 100000;’;
$stmt = $pdo->prepare($q);
if($stmt->execute()) {
$dataAry = new StatementIterator($stmt);
foreach ( $dataAry as $rowData) {
// print_r($rowData);
}
unset($dataAry, $stmt);
}
$timeEnd = microtime(true);
echo “MEMORY End: ” . number_format(memory_get_usage()) . ” byte” . “\n”;
echo “time: ” . bcsub($timeEnd, $timeFst, 5) . “\n”;
「StatementIterator()」は「PDO イテレータで大量のデータを扱う」でまとめ中。
結果1
合計1万レコードに対して何かしたい。
「limit 1000」でクエリを10回投げた場合
MEMORY End: 315,216 byte
time: 0.14270
「limit 10000」でクエリを1回投げた場合
MEMORY End: 314,848 byte
time: 0.14380
結果2
合計10万レコードに対して何かしたい。
「limit 10000」でクエリを10回投げた場合
MEMORY End: 315,232 byte
time: 1.44030
「limit 100000」でクエリを1回投げた場合
MEMORY End: 314,840 byte
time: 1.54710
結果3
合計100万レコードに対して何かしたい。
「limit 100000」でクエリを10回投げた場合
MEMORY End: 315,208 byte
time: 14.43940
「limit 1000000」でクエリを1回投げた場合
結論
件数次第ってのもあるけど、クエリは複数回に分けたほうが速い。
メモリのことを考えると、どっちが良いとは言い切れない。まぁ、ケースバイケースってヤツだな。