活动记录关系谁需要它?
好吧,我对 Rails 查询感到困惑。例如:
Affiche belongs_to :place
Place has_many :affiches
我们现在可以这样做:
@affiches = Affiche.all( :joins => :place )
或者
@affiches = Affiche.all( :include => :place )
,如果有很多附加信息,我们将得到很多额外的 SELECT:
Place Load (0.2ms) SELECT "places".* FROM "places" WHERE "places"."id" = 3 LIMIT 1
Place Load (0.3ms) SELECT "places".* FROM "places" WHERE "places"."id" = 3 LIMIT 1
Place Load (0.8ms) SELECT "places".* FROM "places" WHERE "places"."id" = 444 LIMIT 1
Place Load (1.0ms) SELECT "places".* FROM "places" WHERE "places"."id" = 222 LIMIT 1
...and so on...
并且(原文如此!)每个 SELECT
:joins > 翻倍了!
从技术上讲,我们云只是这样写:
@affiches = Affiche.all( )
结果完全一样! (因为我们已经声明了关系)。将所有数据保留在一个查询中的方法是删除关系并用“LEFT OUTER JOIN”写一大串,但仍然存在多维数组中数据分组的问题以及类似列名的问题,例如 <代码>id。
做错了什么?或者我做错了什么?
更新:
嗯,我有那个字符串 Place Load (2.5ms) SELECT "places".* FROM "places" WHERE ("places"."id" IN (3,444,222,57,663,32,154,20))
和一一选择 id
的列表。奇怪的是,但是当我在每个范围内执行此操作时,我会得到这些单独的选择:
<%= link_to a.place.name, **a.place**( :id => a.place.friendly_id ) %>
标记的 a.place 是产生这些额外查询的位置。
更新 2:
让我做一些数学计算。在控制台中,我们得到:
Affiche Load (1.8ms) SELECT affiches.*, places.name FROM "affiches" LEFT OUTER JOIN "places" ON "places"."id" = "affiches"."place_id" ORDER BY affiches.event_date DESC
<VS>
Affiche Load (1.2ms) SELECT "affiches".* FROM "affiches"
Place Load (2.9ms) SELECT "places".* FROM "places" WHERE ("places"."id" IN (3,444,222,57,663,32,154,20))
结果:1.8ms 与 4.1ms,差不多,令人困惑......
Well, I`m confused about rails queries. For example:
Affiche belongs_to :place
Place has_many :affiches
We can do this now:
@affiches = Affiche.all( :joins => :place )
or
@affiches = Affiche.all( :include => :place )
and we will get a lot of extra SELECTs, if there are many affiches:
Place Load (0.2ms) SELECT "places".* FROM "places" WHERE "places"."id" = 3 LIMIT 1
Place Load (0.3ms) SELECT "places".* FROM "places" WHERE "places"."id" = 3 LIMIT 1
Place Load (0.8ms) SELECT "places".* FROM "places" WHERE "places"."id" = 444 LIMIT 1
Place Load (1.0ms) SELECT "places".* FROM "places" WHERE "places"."id" = 222 LIMIT 1
...and so on...
And (sic!) with :joins
used every SELECT
is doubled!
Technically we cloud just write like this:
@affiches = Affiche.all( )
and the result is totally the same! (Because we have relations declared). The wayout of keeping all data in one query is removing the relations and writing a big string with "LEFT OUTER JOIN", but still there is a problem of grouping data in multy-dimentional array and a problem of similar column names, such as id
.
What is done wrong? Or what am I doing wrong?
UPDATE:
Well, i have that string Place Load (2.5ms) SELECT "places".* FROM "places" WHERE ("places"."id" IN (3,444,222,57,663,32,154,20))
and a list of selects one by one id
. Strange, but I get these separate selects when I`m doing this in each
scope:
<%= link_to a.place.name, **a.place**( :id => a.place.friendly_id ) %>
the marked a.place
is the spot, that produces these extra queries.
UPDATE 2:
And let me do some math. In console we have:
Affiche Load (1.8ms) SELECT affiches.*, places.name FROM "affiches" LEFT OUTER JOIN "places" ON "places"."id" = "affiches"."place_id" ORDER BY affiches.event_date DESC
<VS>
Affiche Load (1.2ms) SELECT "affiches".* FROM "affiches"
Place Load (2.9ms) SELECT "places".* FROM "places" WHERE ("places"."id" IN (3,444,222,57,663,32,154,20))
Comes out: 1.8ms versus 4.1ms, pretty much, confusing...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里的事情真的很奇怪,因为
:include
选项旨在从每个 Affiche 收集place_id
属性,然后使用如下所示的选择查询一次获取所有地点:您可以在导轨控制台。只需启动它并运行该代码片段:
您可能会偶然获取附件,但实际上并未在代码中的某个位置包含位置,而是为每个附件调用 place ,从而使 Rails 为每个附件执行单独的查询。
Something is really strange here because
:include
option is intended to gatherplace_id
attribute from every affiche and then fetch all places at once using select query like this:You can check that in rails console. Just start it and run that snippet:
You might be incidentally fetching affiches without actually including places somewhere in your code and than calling place for every affiche making rails to perform separate query for every one of them.