sql - 使用 LEFT OUTER JOIN 无条件立即加载关联?

标签 sql ruby-on-rails ruby ruby-on-rails-3.1

我们有一个设置了 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/

相关文章:

java - 按一对多关联计数排序的 Hibernate 标准

c# - Mono 中的 SqlClient

ruby-on-rails - 在Rails应用程序中使用Omniauth-oauth2刷新 token

ruby-on-rails - ActiveRecord 条件错误

mysql - Infinity、ActiveRecord 和 MySQL : storage and comparison

mysql - 关于写SQL查询的问题

sql - 在 WHERE 子句中多次使用同一列

mysql - crontab显示mysql错误

ruby - 使用Ruby Mechanize模拟Flash上​​传文件

ruby-on-rails - 有没有人能够在 osx mavericks 上的 rvm 上运行 ruby​​ 1.8.7 和 rails 2.3.x?