3

私はちょうど ActiveRecord と SQL を学んで:includeいて、1 つの SQL クエリを実行するという印象を受けました。だから私がするなら:

Show.first :include => :artist

1 つのクエリを実行し、そのクエリは最初のショーとアーティストを返します。しかし、生成された SQL を見ると、次の 2 つのクエリが表示されます。

[2013-01-08T09:38:00.455705 #1179] DEBUG -- :   Show Load (0.5ms)  SELECT `shows`.* FROM `shows` LIMIT 1
[2013-01-08T09:38:00.467123 #1179] DEBUG -- :   Artist Load (0.5ms)  SELECT `artists`.* FROM `artists` WHERE `artists`.`id` IN (2)

Railscast のビデオの 1 つを見て、著者が:includevs:joinを調べていて、コンソールで出力 SQL を見たところ、それは大きな SQL クエリでしたが、クエリは 1 つだけでした。これが本来あるべき姿なのか、それとも何か足りないのだろうかと思っています。

4

2 に答える 2

7

Active Record には、事前に関連付けをロードする方法が 2 つあります。:includes は、いくつかのヒューリスティックに基づいて、それらのいずれかをトリガーします。

1 つの方法は、関連付けごとに 1 つのクエリを使用することです。最初にすべてのショーを読み込み (1 つのクエリ)、次にすべてのアーティストを読み込みます (2 番目のクエリ)。次に、3 番目のクエリとなるアーティストの関連付けを含める場合。これらのクエリはすべて単純なクエリですが、特定のケースでは利点が得られないことを意味します。クエリが分離されているため、子アソシエーションによって最上位 (ショー) を並べ替えるなどのことはできません。

2 番目の方法は、1 つの大きな結合ベースのクエリですべてをロードすることです。これは常に単一のクエリを生成しますが、より複雑です。関連付けごとに 1 つの結合が含まれ、結果セットを Ruby オブジェクトに戻すコードもより複雑になります。他にもいくつかのまれなケースがあります: ポリモーフィックな belongs_to は処理できず、複数の has_many を同じレベルに含めると非常に大きな結果セットが生成されます)。

Active Record はデフォルトで最初の戦略 (プリロード) を使用しますが、クエリの条件または順序が関連付けを参照していると判断した場合は、2 番目のアプローチにフォールバックします。の代わりにpreloadまたはを使用して、使用する戦略を強制できます 。eager_load:includes

于 2013-01-08T16:36:22.370 に答える
1

Using:includesは、熱心な読み込みを提供するためのソリューションです。この例では、最大 2 つのクエリをロードします。クエリを変更する場合Show.all :include => :artist。これも 2 つのクエリだけを呼び出します。

より良い説明: Active Record Querying Eager Loading

于 2013-01-08T15:07:25.787 に答える