今日もヤバさをI/O中。

新卒1年目のエンジニアブログです。基本的に何かが足りません。

Eloquent ORM vs Query Builder (+ DB Facade )

Laravel で データ取得の方法と述べると、Eloquent ORM と Query Builder (+ DB Facade )の2つが上げられると思います。

今回は、二つのメリットとデメリットを見比べつつ、どういう状況で使えば良いのかを書きます。

Eloquent ORM

Eloquent ORMは、Laravel が提供している O/R マッパです。

ActiveRecord ライクにデータの取得ができます。

メリット

O/R マッパ のメリットを享受できる

  • SQL という別の言語を、アプリケーション( Laravel )に介入せず済む
  • テーブル同士の関係性を定義できる
  • 再利用性や拡張性が高い

など...

今回は、O/R マッパについて述べるわけではないので、詳しくは書きません。

色々柔軟に設定できる

何ができるかは、ドキュメントを読めば一目瞭然です。

Eloquent:利用の開始 5.7 Laravel

  • 独自のグローバルスコープ適応による、独自メソッド実装
  • 特定のイベントをフックにした処理の実行(いわゆるObserverパターン)

拡張性に優れた機能を、有していると言えます

デメリット

O/R マッパ のデメリットを享受する

  • SQL が書けなくても、データ取得ができる
  • ぱっと見、どういうクエリを発行しているのかわからない
  • Eloquent O/R マッパは ActiveRecord パターンで実装されているので、ActiveRecord パターンを覚える必要がある

など...

こちらも、O/R マッパについて述べるわけではないので、詳しくは書きません。

ですが、「ぱっと見、どういうクエリを発行しているのかわからない」は、次のデメリットで関連して触れることになります。

特定のメソッドを使うと、サブクエリを使って実行する

例えば has や whereHas では、exists を使ったサブクエリを実行します。

参考: qiita.com

当然ながら、サブクエリを実行するわけなので、クエリの実行時間が長いことになります。中には join 句を使えばサブクエリにしなくて良いような内容も、サブクエリで実行します。

このデメリットは、O/R マッパのデメリットで挙げた「ぱっと見、どういうクエリを発行しているのかわからない」が躊躇に現れていると思います。

どういう時に使えば良いか

  • パフォーマンスよりも安全性を取りたい
  • 確実に、リレーションに沿ったデータ取得をしたい
  • 特定の状況下での条件付けや、処理の実行を実装したい

Query Builder (+ DB Facade )

Laravel が提供しているクエリを生成するためのメソッド群。

SQL ライクにクエリを書くことができる( Query Builder )他、SQL をそのまま書いて実行する( DB Facade )こともできます。

メリット

Eloquent と比べて高速

join 句を使ったクエリを書けば、Eloquent でサブクエリを使って取得している処理よりも早くなります。

また、以下 URL では、同じ実行結果でも、Eloquent O/R マッパ に比べて Query Builder (+ DB Facade )の方が早いことを主張しています。

参考:https://www.youtube.com/watch?v=3TJfR1Ta4GU

どういうクエリを実行しているのかはわかりやすい

SQL 文と書き方に大きな差はないので、なんのクエリが発行されているかは非常にわかりやすいです。

SQL を書けさえすれば学習コストは低い

どんなメソッドがあるかは覚える必要があるものの、それ以外に必要なことは、SQL 文を書けることだけです。

デメリット

自力で考慮しなければいけない点がある

  • テーブル同士の結合は自身で行う必要があるため、リレーションを正しく把握して反映する必要がある
  • 論理削除の条件は、自分で条件指定する
  • そもそも SQL 文で間違った書き方を書いてはいけない

など...

これらを正しく考慮できていないと、意図しないデータを取得してしまう場合があります。

また、個人開発ではなくチームによる開発であれば、レビュアーが上記の点を考慮してコードレビューしなければなりません。

どういう時に使えば良いか

  • 複雑な条件や大量のデータを扱うので、パフォーマンスを求めたい(検索画面、一覧画面とか)
  • 複雑な条件のクエリを、発行したい