LoginSignup
1

More than 3 years have passed since last update.

Laravel でむやみに Model all() を使うとパフォーマンスが悪くなる

Posted at

はじめに

(サンプルのバージョンは 5.5 で書いてます)

Laravelって便利。リレーションだって簡単に貼れます。
しかし、書き方によって予期しない挙動したので備忘録として残します。

実際にやってみた

まずサンプルとして、ユーザ情報を扱うテーブルと、トレーニング情報を扱うテーブルを用意。

CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(64) NOT NULL COMMENT '名前',
  `deleted_at` datetime DEFAULT NULL COMMENT '削除日時',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='ユーザ';

CREATE TABLE `trainings` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `trained_user_id` int(10) unsigned NOT NULL COMMENT 'トレーニング者',
  `summary` varchar(255) NOT NULL COMMENT '概要',
  `deleted_at` datetime DEFAULT NULL COMMENT '削除日時',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='トレーニング';

トレーニング情報と一緒に、トレーニング者のユーザ名を取得したいとき、
Modelクラスでこのように関数を設置し、belongsToでリレーションを貼っておくと、
Training情報を取得した時にも trained_user関数 を呼び出しただけで users 情報を取得できます。

Training.php
use Illuminate\Database\Eloquent\Model;

/**
 * Class Training
 */
class Training extends Model
{
    public function trained_user()
    {
        return $this->belongsTo(User::class);
    }
}
$trainings = Training::all();
$trainings[0]->trained_user->name; // トレーニング者の名前が取れる

でも、やったね!と思ってクエリログを見ると愕然します...

select * from `trainings` where `trainings`.`deleted_at` is null
select * from `users` where `users`.`id` = '1' and `users`.`deleted_at` is null limit 1
select * from `users` where `users`.`id` = '2' and `users`.`deleted_at` is null limit 1
select * from `users` where `users`.`id` = '3' and `users`.`deleted_at` is null limit 1

みてください、・・・ユーザ分毎回SQL投げてる;;;;
めっちゃパフォーマンス悪い;;;;

反省して書き直し。

$trainings = Training::with(['trained_user'])->get(); // trained_user を設定する
$trainings[0]->trained_user->name; // 同様にトレーニング者の名前が取れる

クエリログは・・・

select * from `trainings` where `trainings`.`deleted_at` is null
select * from `users` where `users`.`id` in ('1', '2', '3') and `users`.`deleted_at` is null

期待どおりの結果になりました!
というわけで、リレーション貼ってる時は気をつけましょう〜

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