我们有一个设置了 has_one 关联的模型:
class User
has_one :shirt
class Shirt
belongs_to :user
目前,我们可以在检索有限的用户数组时添加.includes(:shirt)
,它将按预期执行两个 SQL 查询。
我们面临的问题是加载页面的查询正在执行以下操作:
SELECT "shirt".* FROM "shirts" WHERE "shirt"."user_id" IN (2147521, 2147522 ... )
当检索 50 个用户和衬衫时,这对我们来说性能不是很好。我们的用户和衬衫表很大。我们注意到,通过强制 Rails 使用 INNER JOIN,速度有了很大的提高:
User.where( ... ).joins(:shirts).includes(:shirts).limit(50)
不幸的是,这只会返回拥有衬衫的用户。我们需要能够返回有限的用户群,无论他们是否有关联的衬衫。
是否有办法强制 Rails 使用 LEFT OUTER JOIN 而不是默认的双查询方法来预先加载关联对象?
编辑
通过添加 where
子句,无论关联对象上的值是否为 null,该子句都返回 true。它似乎并不介意是否没有关联的对象,至少在 Postgres 上是这样。
User.where( ... ).includes(:shirt).where("shirts.created_at IS NULL OR shirts.created_at IS NOT NULL")
这解决了问题,但不太理想,有没有办法使用 LEFT OUTER JOIN 而不是默认的双查询方法?
最佳答案
如 this post 中所述,在大多数情况下,2 查询方法被认为更快(尽管对于您所拥有的一对一关系来说不一定如此)。如果您想强制 Rails 使用 LEFT OUTER JOIN,您可以通过在关联表上添加无意义的过滤器来实现:
User.where( ... ).
includes(:shirts).
where("shirts.id IS NULL OR shirts.id = shirts.id").
limit(50)
关于sql - 使用 LEFT OUTER JOIN 无条件立即加载关联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13915412/