ブログBlog
PG向け:【PHP】array_column関数で検索処理を爆速に上げよう
投稿日:2022年06月23日 テクノロジー
こんにちは、江宮です!
多数データのリストを処理するときに、表示スピードが問題になってくることあると思います。
そんなときにPHPのarray_column関数を使用することで、大幅に処理スピードを軽減させることができます。
例えば以下のような状況下です。
【複数のレンタルビデオ店を管理している本部が全店舗のレンタル履歴リストを表示する処理】
レンタル日 | レンタル店名 | 商品名 |
2022-06-20 | 大阪店 | 劇場版「鬼滅の刃」無限列車編 |
2022-06-20 | 東京店 | 千と千尋の神隠し |
2022-06-21 | ニューヨーク店 | タイタニック |
2022-06-22 | パリ店 | アナと雪の女王 |
2022-06-23 | ロンドン店 | 君の名は。 |
履歴テーブルには履歴ID・レンタル日・レンタル店ID・商品IDが格納されているとします。
history_id | 履歴ID |
rental_date | レンタル日 |
store_id | レンタル店ID |
goods_id | 商品ID |
store_id | レンタル店ID |
store_name | レンタル店名 |
store_id | 商品ID |
store_name | 商品名 |
欲しいデータは以下の連想配列データです。
$wanted_list => [
5 => [
’history_id’ => 5,
’rental_date’ => ‘2022-06-19’,
’store_name’ => ‘大阪店’,
’goods_name’ => ‘劇場版「鬼滅の刃」無限列車編’
],
6 => [
’history_id’ => 6,
’rental_date’ => ‘2022-06-20’,
’store_name’ => ‘東京店’,
’goods_name’ => ‘千と千尋の神隠し’
],
7 => [
’history_id’ => 7,
’rental_date’ => ‘2022-06-21’,
’store_name’ => ‘ニューヨーク店,
’goods_name’ => ‘タイタニック’
],
8 => [
’history_id’ => 8,
’rental_date’ => ‘2022-06-22’,
’store_name’ => ‘パリ店’,
’goods_name’ => ‘アナと雪の女王’
],
9 => [
’history_id’ => 9,
’rental_date’ => ‘2022-06-23’,
’store_name’ => ‘ロンドン店’,
’goods_name’ => ‘君の名は。’
],
]
処理の流れは以下の通りです。
- 履歴テーブルからレンタル日、レンタル店ID、商品IDを取得
- レンタル店テーブルからレンタル店IDをもとにレンタル店名を取得
- 商品テーブルから商品IDをもとに商品名を取得
このときSQLのみの処理だと、履歴テーブルからレンタル店ID・商品IDを取得後、さらにループでそれらのIDをもとに2つのテーブルからレンタル店名・商品名を取得する処理になります。
連想配列で履歴データを取得
SELECT history_id, rental_date, store_id, goods_id FROM history_table;
$history => [
0 => [‘history_id’ => 5, ‘rental_date’ => ‘2022-06-19’, ‘store_id’ => 10, ‘goods_id’ => 20],
1 => [‘history_id’ => 6, ‘rental_date’ => ‘2022-06-20’, ‘store_id’ => 11, ‘goods_id’ => 21],
2 => [‘history_id’ => 7, ‘rental_date’ => ‘2022-06-21’, ‘store_id’ => 12, ‘goods_id’ => 22],
3 => [‘history_id’ => 8, ‘rental_date’ => ‘2022-06-22’, ‘store_id’ => 13, ‘goods_id’ => 23],
4 => [‘history_id’ => 9, ‘rental_date’ => ‘2022-06-23’, ‘store_id’ => 14, ‘goods_id’ => 24],
]
欲しい配列データ作成
foreach($history as $row)
{
$wanted_list[$row[‘history_id’]][‘hstory_id’] = $row[‘history_id’];
$wanted_list[$row[‘history_id’]][‘reantal_date’] = $row[‘rental_date’];
$wanted_list[$row[‘history_id’]][‘store_name’] =
戻り値(SELECT store_name FROM store_table WHERE store_id = $row[‘store_id’]);
$wanted_list[$row[‘history_id’]][‘customer_name’] =
戻り値(SELECT customer_name FROM customer_table WHERE customer_id = $row[‘customer_id’]);
}
※欲しかった配列データ
$wanted_list => [
5 => [
’history_id’ => 5,
’rental_date’ => ‘2022-06-19’,
’store_name’ => ‘大阪店’,
’goods_name’ => ‘劇場版「鬼滅の刃」無限列車編’
],
6 => [
’history_id’ => 6,
’rental_date’ => ‘2022-06-20’,
’store_name’ => ‘東京店’,
’goods_name’ => ‘千と千尋の神隠し’
],
7 => [
’history_id’ => 7,
’rental_date’ => ‘2022-06-21’,
’store_name’ => ‘ニューヨーク店,
’goods_name’ => ‘タイタニック’
],
8 => [
’history_id’ => 8,
’rental_date’ => ‘2022-06-22’,
’store_name’ => ‘パリ店’,
’goods_name’ => ‘アナと雪の女王’
],
9 => [
’history_id’ => 9,
’rental_date’ => ‘2022-06-23’,
’store_name’ => ‘ロンドン店’,
’goods_name’ => ‘君の名は。’
],
]
結果は取得できますが、履歴一覧抽出処理+各履歴データ×2項目の検索処理を実行するのでデータが莫大であればかなりの処理時間がかかります。
例では11回のSQL実行になりますがが、履歴データが200行あったとしたら401回SQLが実行されます。
ここで、処理スピードを上げるためにarray_column関数の出番です。
・履歴一覧抽出処理
SELECT history_id, store_id, goods_id, customer_id, address_id FROM history_table;
※連想配列で履歴データを取得
$history => [
0 => [‘history_id’ => 5, ‘rental_date’ => ‘2022-06-19’, ‘store_id’ => 10, ‘goods_id’ => 20],
1 => [‘history_id’ => 6, ‘rental_date’ => ‘2022-06-20’, ‘store_id’ => 11, ‘goods_id’ => 21],
2 => [‘history_id’ => 7, ‘rental_date’ => ‘2022-06-21’, ‘store_id’ => 12, ‘goods_id’ => 22],
3 => [‘history_id’ => 8, ‘rental_date’ => ‘2022-06-22’, ‘store_id’ => 13, ‘goods_id’ => 23],
4 => [‘history_id’ => 9, ‘rental_date’ => ‘2022-06-23’, ‘store_id’ => 14, ‘goods_id’ => 24],
]
・レンタル店データ抽出処理
SELECT store_id, store_name FROM store_table;
※連想配列でレンタル店データを取得
$store_names => [
0 => [‘store_id’ => 10, ‘store_name’ => ‘大阪店’],
1 => [‘store_id’ => 11, ‘store_name’ => ‘東京店’],
2 => [‘store_id’ => 12, ‘store_name’ => ‘ニューヨーク店’],
3 => [‘store_id’ => 13, ‘store_name’ => ‘パリ店’],
4 => [‘store_id’ => 14, ‘store_name’ => ‘ロンドン店’],
]
※キー名を要素番号からstore_idに変換
$store_name_list = array_column($store_name_list, NULL, ‘store_id’ );
$store_names => [
10 => [‘store_id’ => 10, ‘store_name’ => ‘大阪店’],
11 => [‘store_id’ => 11, ‘store_name’ => ‘東京店’],
12 => [‘store_id’ => 12, ‘store_name’ => ‘ニューヨーク店’],
13 => [‘store_id’ => 13, ‘store_name’ => ‘パリ店’],
14 => [‘store_id’ => 14, ‘store_name’ => ‘ロンドン店’],
]
・商品データ抽出処理
SELECT store_id, store_name FROM store_table;
※連想配列で商品データを取得
$store_names => [
0 => [‘goods_id’ => 20, ‘goods_name’ => ‘劇場版「鬼滅の刃」無限列車編’],
1 => [‘goods_id’ => 21, ‘goods_name’ => ‘千と千尋の神隠し’],
2 => [‘goods_id’ => 22, ‘goods_name’ => ‘タイタニック’],
3 => [‘goods_id’ => 23, ‘goods_name’ => ‘アナと雪の女王’],
4 => [‘goods_id’ => 24, ‘goods_name’ => ‘君の名は。’],
]
※キー名を要素番号からgoods_idに変換
$goods_name_list = array_column($goods_name_list, NULL, ‘goods_id’ );
$goods_names => [
20 => [‘goods_id’ => 20, ‘goods_name’ => ‘劇場版「鬼滅の刃」無限列車編’],
21 => [‘goods_id’ => 21, ‘goods_name’ => ‘千と千尋の神隠し’],
22 => [‘goods_id’ => 22, ‘goods_name’ => ‘タイタニック’],
23 => [‘goods_id’ => 23, ‘goods_name’ => ‘アナと雪の女王’],
24 => [‘goods_id’ => 24, ‘goods_name’ => ‘君の名は。’],
]
欲しい配列データ作成
foreach($history as $row)
{
$wanted_list[$row[‘history_id’]][‘hstory_id’] =
$row[‘history_id’];
$wanted_list[$row[‘history_id’]][‘reantal_date’] =
$row[‘rental_date’];
$wanted_list[$row[‘history_id’][‘store_name’]] =
$history[$row[‘history_id’]][$store_names[$row[‘store_id’][‘store_name]];
$wanted_list[$row[‘history_id’][‘goods_name’]] =
$history[$row[‘history_id’]][$goods_names[$row[‘goods_id’][‘goods_name]];
}
※欲しかった配列データ
$wanted_list => [
5 => [
’history_id’ => 5,
’rental_date’ => ‘2022-06-19’,
’store_name’ => ‘大阪店’,
’goods_name’ => ‘劇場版「鬼滅の刃」無限列車編’
],
6 => [
’history_id’ => 6,
’rental_date’ => ‘2022-06-20’,
’store_name’ => ‘東京店’,
’goods_name’ => ‘千と千尋の神隠し’
],
7 => [
’history_id’ => 7,
’rental_date’ => ‘2022-06-21’,
’store_name’ => ‘ニューヨーク店,
’goods_name’ => ‘タイタニック’
],
8 => [
’history_id’ => 8,
’rental_date’ => ‘2022-06-22’,
’store_name’ => ‘パリ店’,
’goods_name’ => ‘アナと雪の女王’
],
9 => [
’history_id’ => 9,
’rental_date’ => ‘2022-06-23’,
’store_name’ => ‘ロンドン店’,
’goods_name’ => ‘君の名は。’
],
]
3回しかSQL文を発行していないので、データ量が大きくなればなるほど圧倒的に早くなります!