最近、現場で久しぶりにPHPを触っていました。
PHPは配列の扱いがとても楽で、というのも添字配列と連想配列の区別が存在しないため、雑にいうとJavaで言えばArrayとList、Mapの区別がないといった感じでしょうか。
$a = [];
$a[] = 'one';
$a['key1'][] = 'two';
$a[] = 'three';
$a['key1']['key2'] = 'four';
と配列に連想配列と添字が混在した形で値を追加することができます。これを出力してみますと、
print_r($a)
Array (
[0] => one
[key1] => Array (
[0] => two
[key2] => four
)
[1] => three
)
といった添字と連想配列が混在した結果がえられるかと思います。
この手軽に連想配列が使える特徴を活かして、効率よく大量データを処理するよう僕の場合は常に意識しています。
例えば、CSVファイルから取り込んだユーザーリストのIDがDBに存在しているかチェックをし、存在していれば更新する、といった処理があるとします。
//簡単のため、CSV行数は1000件とする
foreach ($csv_rows as $row) {
$user_id = $row[0];
$result = $table('user')-> where('user_id', $usr_id)->get();
if ($result) {
$result = $table('user')-> where('user_id', $user_id)->upate(['name' => $row[1], 'age' => $row[2]);
}
}
と1000件程度のCSVデータを毎回DBに存在チェックのため問い合わせるよりも、
//簡単のため、CSV行数は1000件とする
$user_ids = [];
foreach ($csv_rows as $row) {
$user_ids[] = $row[0];
}
$results = [];
if ($user_ids) {
$results = $table('user')->where('user_id', $usr_ids)->get();
}
$users = [];
foreach ($results as $res) {
//ここでユーザーIDをキーに連想配列に格納
$users[$res->user_id] = $res;
}
foreach ($csv_rows as $row) {
$user_id = $row[0];
// 連想配列に一致するデータのみ更新
if ($users[$row[0]) {
$table('user')->where('user_id', $user_id)->upate(['name' => $row[1], 'age' => $row[2]);
}
}
とコードは長くなりますが、まとめてDBからユーザー情報を一式取得し、ユーザーIDをキーにした連想配列に格納し、一致するCSVデータのに更新するようにした方が
DBサーバーへの負荷低減に繋がるのと処理速度も改善できると思います。
これが数万以上になりますと差は歴然としてきます。
このような形で3分かかっていた数万件程度の処理を連想配列を活用した処理に変更後、5秒に短縮することができました。
参考になれば幸いです。