skillup

技術ブログ

Database

joinとeager loading

投稿日:2018年7月22日 更新日:

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

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

通常のjoin

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

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

ループの中で取得

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

hasManyなどを動的に使用

Laravelだとリレーションを以下のように表現することでプロパティの一部として取得できます。User-Postの関係が1:Nとします。

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

上記のようなリレーションを動的に組む方法がベストっぽいです。

これだと親のレコードの中にプロパティとして格納されるため、通常のjoinと違ってカラムが消されたりってことはありません。

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

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

eager loading

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

こうすることで

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

ということができます。Laravelですと、以下のようにwithを付与することで解決します。

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

【Laravel】動的プロパティとリレーションメソッド。そしてN+1問題を真剣に調べてみた

参考リンク

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

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

-Database
-

執筆者:


comment

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

関連記事

no image

アンチパターン 参照渡しと値渡し+キー情報の設定+同一値を複数テーブルに配置+正規化が不十分+集計表+不適切なステータス値

本日は自分がデータベースの設計をしていて気を付かないといけないなーと思った点などを。 注意点としては設計のミスは実装で取り返しにくいことが多いので極力気を付けましょう。あといろいろなテーブルのパターン …

no image

ロック(排他制御)について

ECなどでの開発の場合、当然在庫数によって購入できるか、いなかがかわってきますが、複数人で同時にアクセスする際、処理の整合性を見る必要がでてきますので、ロックのが概念が大事になってきます。 そこでロッ …

no image

postgresの外部キー制約やcascadeについて

外部キーを貼っておくと、当然、削除などを行うときにエラーになり、truncateも当然できなくなりますが、cascadeをつけることで、関連するテーブルまで一気にtruncateされます。 [cray …

no image

MySQLでtext型が大量にあるもののリストア 

MySQLでのリストアについて。 先日実務でtext型のカラムが複数あるテーブルを読もうとしたら下記エラーがでてこけました。

なにやら …

no image

SQL結合 サブクエリに関して

今回はサブクエリに関してです。 もちろんSQL実践入門を読み進めています。 SQL上ではテーブル、ビュー、サブクエリというのは機能的にはそれほど変わらず主にパフォーマンスの点で違いがでてきます。 以下 …

アーカイブ