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

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

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

no image

オプティマイザと実行計画

データベースがSQLを受け取って処理を実行する前には下記のような段階があります。 Contents1 パーサー2 オプティマイザ3 カタログマネージャー4 参考リンク パーサー SQL構文のチェックし …

no image

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

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

no image

HAVING句がらみの計算式

「達人に学ぶSQL徹底指南書」読んでますが、かなり難しいものがでてきましたね。 テーブルは前回のものと同じ以下のものを使います。 name | income ————+——– サンプソン | 4000 …

no image

CakePHPでの数字カンマ区切り&PHP&MySQL曜日の出力

今回は主に時間やお金の表示など、出力に関するネタです。 Contents1 Cakeでのカンマ区切り1.1 単純なカンマ区切り 例1,0001.2 \をつけるケース 例 \1,0001.3 円をつける …

アーカイブ