skillup

技術ブログ

Database

joinとeager loading

投稿日:

フレームワークでデータをORMがらみでjoinするときのネタ。

自分の場合はLaravel。他のフレームワークでも考え方は通じるものあるかと・・

通常のjoin

select句に何も指定せずjoin句を使うとプロパティがフラットになってしまいます。これだとカラム名が競合した時に片方が消されてしまいます。

例えばorderからorderitemをjoinしようと思った時にorderの1プロパティの中にorderitemがあり、この中にorderitemの全てのプロパティがあるというのが理想的です。

ループの中で取得

親(order)の数×子供の数(orderitem)となってしまい計算量的にありえないのでNG。

hasManyなどを動的に使用

https://readouble.com/laravel/5.1/ja/eloquent-relationships.html

上記のようなリレーションを動的に組む方法がベストっぽいです。これだと親のレコードの中にプロパティとして格納されるため、通常のjoinと違ってカラムが消されたりってことはありません。

ただこの手法だとjoin自体が実行されるのは親自体(order)をループする時になり、DBへのアクセス数が親の数×子供の数となってしまいます。(これが俗にいうN+1問題と言われるものらしいです。)

通常の取得をlazy loadingというようですね。

ちなみにディフォルトでhasManyなどのjoin関係を定義しておくと、親が絡む全てのSQLで自動的に子供がついてきてしまい、非常にめんどくなりますので、動的にリレーションの関係は作るようにしましょう。

eager loading

これを解決するのがeager loadingという手法のようでクエリを発行した瞬間にDBへのアクセスも終わります。

こうすることで

  • 親のプロパティの中に子供のオブジェクトを格納し、
  • かつ計算量も抑える

ということができます。

えらい単純なことですが、これに行きつくまでにそこそこ時間がかかりました・・・(汗)

参考リンク

laravelじゃないですが、参考になりそう。

CakePHP3のORMを使う際に欠かせない概念について

-Database
-

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

no image

SQL基礎 複雑なSQLの組み方

SQLの本を見ますとかなり複雑なSQLが書かれていることが多いです。 これは頑張っても無理では・・・と思っていましたが、ポイントしては 原則として必ず図に書く まずは問題を細かく分割する 細部から切り …

no image

sql_modeに関して

開発では動いていたのに本番ではint型のカラムで空白が入らない!みたいなエラーが出て、データベースにデータが入らないことが発覚し、調査をすることに・・・ sql_modeが原因でした・・・ sql_m …

no image

EXISTSと集合

前回に引き続きEXISTSの問題です。 下記のようなテーブル(projects)があり、 project_id | step_nbr | status ———&#8 …

no image

エンティティの抽出と主キー決定

主に設計に関することのメモ。 Contents1 業務フロー分析2 エンティティの抽出3 エンティティの関連付け4 主キーの抽出を行う4.1 主キーの特徴4.2 サロゲートキーのメリット4.3 サロゲ …

no image

MySQLのパフォーマンスチェックなどについて

常日頃MySQLをつかっているのですがパフォーマンスのチェックなどをあまりしていなかったため、これをチョクチョクしていこうかなあと思っております。 簡単に使えるツール(ただし5.1.4から)としては標 …