1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHP】配列操作とSQLの処理の違いを検証してみた

Posted at

自分が現場で学んだ事の一つに
データを一括取得した後に関数などでソートするより、取得の段階でSQLにて条件で絞った方がいい
という事があります。

まあ、普通に考えて100万件データを取得してソートして結果10万になるのと、SQLの段階で絞って10万件取得するのとでは後者の方が「処理速度」や「メモリの消費」の観点で効率がいいのはなんとなくわかりますよね。

でも、実際に比較したわけではないので、試しに検証してみましょう!という事で検証してみたいと思います。興味がある人は自分で実施してみてはいかがでしょうか。

実行環境

  • macOS (Sequoia 15.1.1)
  • PHP 8.3.12
  • MySQL 9.0.1

①検証用データを格納するテーブルの作成

とりあえずカラム数が少ないと検証として難しいので、一旦6つほどカラムを持ったテーブルを作成します。

CREATE TABLE test (
    id INT AUTO_INCREMENT PRIMARY KEY,
    value INT NOT NULL,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    status ENUM('active', 'inactive') DEFAULT 'active'
);

②適当なテストデータを挿入

10万件ほどテストデータを挿入してみます。

SET @n := 0;

INSERT INTO test (value, name, status) 
SELECT FLOOR(RAND() * 1000), CONCAT('Name', @n := @n + 1), IF(@n % 2 = 0, 'active', 'inactive')
FROM (SELECT 1 FROM information_schema.tables LIMIT 100000) AS numbers;

③検証用のPHPファイルを2つ作成

今回の条件は以下のようにします。
◯valueが500以上のものを取得する。

これを元に、
(1)配列関数を使用して取得
(2)SQLで最初から絞り込んで取得
のパターンに分けてソースコードを作成します。

※今回はmysqliを使用します。DB情報は自身のローカルの情報に合わせてください。

(1)配列関数を使用して取得
test1.php

<?php
$start_time = microtime(true);

// データベース接続
$conn = new mysqli("localhost", "root", "password", "db_name");
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// 全データを取得
$result = $conn->query("SELECT * FROM test");

// 配列にデータを格納
$data = [];
while ($row = $result->fetch_assoc()) {
    $data[] = $row;
}

// 配列関数で条件を絞り込み
$data = array_filter($data, function($row) {
    return $row['value'] > 500;
});

// 絞り込んだ結果をインデックス付き配列に戻す
$data = array_values($data);

$conn->close();

// 処理時間の計測
$end_time = microtime(true);
echo "配列関数を使用して取得";
echo "取得件数: ".count($data)."件\n";
echo "PHPで条件を絞る場合の処理時間: " . ($end_time - $start_time) . "秒\n";
echo "メモリ使用量: " . memory_get_peak_usage(true) . "バイト\n";
?>

(2)SQLで最初から絞り込んで取得
test2.php

<?php
$start_time = microtime(true);

// データベース接続
$conn = new mysqli("localhost", "root", "password", "db_name");
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// SQLで条件を絞る
$result = $conn->query("SELECT * FROM test WHERE value > 500");

// データを配列に格納
$data = [];
while ($row = $result->fetch_assoc()) {
    $data[] = $row;
}
$conn->close();

// 処理時間の計測
$end_time = microtime(true);
echo "取得件数: ".count($data)."件\n";
echo "SQLで条件を絞る場合の処理時間: " . ($end_time - $start_time) . "秒\n";
echo "メモリ使用量: " . memory_get_peak_usage(true) . "バイト\n";
?>

④実際に実行

test1.phpとtest2.phpを保存したパスに移動して、各スクリプトを実行します。
※自分はDesktopに保存しました。

スクリーンショット 2024-12-27 14.57.11.png

実行結果

(1)配列関数を使用して取得
処理時間:0.2064
メモリ使用量:82.32MB
(2)SQLで最初から絞り込んで取得
処理時間:0.1138
メモリ使用量:39.85MB

結論:SQLの方が処理時間・メモリ使用量ともに約2倍ほどの効率が良い

※データ数や構造、使用する関数によって多少前後するので、ご理解ください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?