Rails中joins与references的区别及两种查询写法的使用共识
Rails中
joins与references的区别及两种查询写法对比 一、joins和references的核心差异
joins:用来生成SQL的JOIN语句(默认是INNER JOIN,也可指定LEFT JOIN),核心作用是关联多张表做条件过滤。它只会返回关联条件匹配的记录,而且默认不会预加载关联模型的数据——查询完之后访问关联对象,会触发N+1查询。references:不能单独使用,必须配合includes。当你用includes关联表,同时又在where里用原生SQL字符串过滤关联表字段时,references会强制Rails生成JOIN语句(而不是尝试用子查询实现),同时保留includes的预加载特性,避免后续访问关联数据时的N+1问题。
二、两种查询写法的具体差异
写法一:User.includes(:sites).where("sites.name = 'test'").references(:sites)
- 生成
LEFT OUTER JOIN语句,同时会预加载匹配条件的sites数据,查询后直接访问user.sites不会触发额外SQL。 - 虽然是左关联,但因为
where条件过滤了sites.name = 'test',最终返回的是拥有符合条件sites的User(和内联结果类似),但同时把关联的sites数据也加载好了。
写法二:User.joins(:sites).where(sites: { name: "test"})
- 生成
INNER JOIN语句,只返回存在name为test的sites关联的User,不会预加载sites数据——后续访问user.sites会触发N+1查询。 - 用哈希形式的
where条件更安全,Rails会自动处理表名、字段的转义,避免SQL注入风险,写法也更简洁直观。
三、优先选择的普遍共识
- 如果你只需要查询符合条件的User,后续不需要访问关联的
sites数据,优先用joins的写法。它生成的SQL更轻量,没有预加载的额外开销,哈希条件也更安全。 - 如果你查询后需要频繁操作关联的
sites数据,要避免N+1问题,就用includes + references的写法,一次查询就能把User和对应sites的数据都加载完成。
内容的提问来源于stack exchange,提问作者elabmot
相关产品推荐
相关产品推荐

