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

mavenのリモートリポジトリについて

JPAでO/Rマッパーに慣れてからというもの通常のSQLをごりごり書くのが億劫になってきました。 億劫というかいろいろとリスクがありますね。 問題点としてはコンパイルするときにエラーが検知できなかった …

no image

Cakeでのリレーションについて

いまさらながらCakeのリレーションについての復習。 基本から。 Contents1 基本的なリレーション1.1 1対N1.2 N対11.3 動的な紐づけ 基本的なリレーション 下記のようなテーブル構 …

no image

MySQL小ネタ テーブル単位のリストア・SQLの小ネタ(バックスラッシュの検索)

MySQLのちょい小ネタ。 Contents1 テーブル単位でバックアップ&リストア2 バックスラッシュの入ったSQLについて テーブル単位でバックアップ&リストア 1 通常のdump(データベース単 …

no image

HAVING句について

本日はHAVINGについて。 かろうじて用法はしっており、たまに使うこともありますが、あまりしっかり理解しているとはいえない状況ですので、掘り下げてみようと思います。 WHEREとは違い、抽出した結果 …

no image

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

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