[PHP] 多重配列の処理をもっと早く処理できるようにする方法

PHP
2重ループは、メモリキャッシュすることで、高速化できるので、仕事でやってみたらかなり効果的だったという備忘録です。

多重ループはどんな時に発生する?

2つの別々のデータベースから、片方からはマスターデータ(ユーザーデータなど)、もう片方からは実行データ(売り上げデータなど)をリストで取得して、それらを突合する時に多重ループで処理する必要に迫られます。

サンプル

営業部門のユーザー登録されているデータベースAから、ユーザーリストの取得 ユーザーデータJSON [ { "id" : 1, "name" : "tanaka" }, { "id" : 2, "name" : "suzuki" }, { "id" : 3, "name" : "naito" } ] 次にデータベースBから、売上実績データを取得 売り上げデータJSON [ { "id" : 1, "price" : 10000, "user_id" : 1 }, { "id" : 2, "price" : 5000, "user_id" : 3 }, { "id" : 3, "price" : 7500, "user_id" : 2 } ]

PPAP合体!

上記で取得したデータリスト2つをuser_idを元に結合してみたいと思います。 <?php $a = [ [ "id" => 1, "name" => "tanaka" ], [ "id" => 2, "name" => "suzuki" ], [ "id" => 3, "name" => "naito" ] ]; $b = [ [ "id" => 1, "price" => 10000, "user_id" => 1 ], [ "id" => 2, "price" => 5000, "user_id" => 3 ], [ "id" => 3, "price" => 7500, "user_id" => 2 ] ]; foreach($a as $a_key => $a_val){ foreach($b as $b_key => $b_val){ if($a_val['id'] === $b_val['user_id']){ $b[$b_key]['name'] = $a_val['name']; break; } } } echo '<pre>'; print_r($b); 実行結果 Array ( [0] => Array ( [id] => 1 [price] => 10000 [user_id] => 1 [name] => tanaka ) [1] => Array ( [id] => 2 [price] => 5000 [user_id] => 3 [name] => naito ) [2] => Array ( [id] => 3 [price] => 7500 [user_id] => 2 [name] => suzuki ) ) 数が少なくて対した時間がかかりませんが、これが、ユーザーリストも売り上げリストも1000ずつぐらいの桁数があると考えると、100万回のループ処理が発生します。 途中でbreak処理をしていますが、こうした場合は、最大値で考えたほうがいいでしょう。

メモリ化して高速化

次に、上記のように無駄にループ処理を行わずに、次のようにメモリにデータを保持してみるともっとスッキリ処理できます。 データは同じなので、合体処理の箇所のみ書き換えてみました。 $a2 = []; foreach($a as $a_key => $a_val){ $a2[$a_val['id']] = $a_val; } foreach($b as $b_key => $b_val){ $b[$b_key]['name'] = $a2[$b_val['user_id']]['name']; } echo '<pre>'; print_r($b); これで同じ結果が返ります。 なんだかプログラミングもスッキリするし、処理速度も早くなるならこっちのほうがいいですね。 ただし、上記のプログラムは、いくつか気をつける点があり、user_idが必ず存在する場合に限ります。 if文を入れ込めばいいだけですが・・・

どのくらいの処理速度の向上が見込めるの?

単純にループの回数だけみると、最初のプログラムは、aの個数 × bの個数ですが、 次のプログラムは、aの個数 + bの個数です。 でも実際に大容量で速度計測をしてみると、せいぜい、50%から60%程度の軽減になるので、この辺はコンピュータスペックなども影響してきます。 でも、速度が半分になるって、まあまあな改善ポイント高いですよね。 他にも色々な方法で処理速度を上げることができるので、こうしたアルゴリズムにトライしてプログラミングスキルもアップしてみてはいかがでしょうか?