その他
    ホーム 技術発信 DoRuby :joinと:includeの区別について

    :joinと:includeの区別について

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    :joinと:includeの区別について、いままであまり分からかなったので、実行してみて、メモします。


    :joinと:includeの区別について、いままであまり分からかなったので、実行してみて、メモします。

    (1):includeは最初に関連モデルを全て取得し、その後、キャッシュからロードされる

    products,product_detailsテーブルがhas_oneの関係です。
    現在、A,Bデータベースの上記2テーブルのデータを比較して、差分分をAからBへコピーする機能です。

    set_db(a)
    a_prodcut = Product.find(10)

    set_db(b)
    b_prodcut = Product.find(10)


    ※set_db(x)はDB指向を指定するメソッドの仮名です。

    a_prodcut.product_detailのcommentカラムの内容を取得したい場合、
    a_prodcut.product_detail.commentですと
    「select * from product_details where product_id = 10」sqlが発行されています。
    この場合、DBがbに指向されているので、取得したのはa_prodcutのproduct_detailではなく、
    b_prodcutが紐付いているproduct_detailです。
    joinでやって、同じく、sqlが発行されています。

    includeでやってみます。
    set_db(a)
    a_prodcut = Product.find(:first,:conditions => [“products.id = 10”], :include => [:item_content])

    set_db(b)
    b_prodcut = Product.find(:first,:conditions => [“products.id = 10”], :include => [:item_content])


    a_prodcut.product_detail.commentしたら正しい内容が取得できます。
    :includeは、最初に関連モデルを全て取得しているため、a_prodcut.product_detailがキャッシュからロードされます。

    (2):includeと:selectは併用できない
    :includeは、最初に関連モデルを全て取得しているため、:selectの指定が無効となります。
    :joinの場合、:selectが使えます。

    追記:

    巨大なテーブルの場合、:includeはすべてキャッシュにロードするので、パフォーマンスが落ちるかもしれないとの話もあったようです。
    >:includeは、最初に関連モデルを全て取得しているため
    結局、↑この特性を理解したうえで、状況に合わせて使えってことですね

    2011-10月

    久しぶりに追加します。:joinsは、関連モデルを検索条件に追加する場合に使うべし。includeを使うと、:includeは、最初に関連モデルを全て取得しているため、キャッシュからロードされるということで期待の結果がヒットできない可能性が十分あります。

    記事を共有