28

这是关于 ActiveRecord 查询方法的问题:

  • first查找第一条记录(如果提供了参数,则查找前 N 条记录)。如果没有定义顺序,它将按主键排序。
  • take给出一条记录(如果提供了参数,则给出 N 条记录),没有任何隐含顺序。顺序将取决于数据库实现。如果提供订单,它将受到尊重。

用例:根据唯一属性从数据库中检索记录,例如。

User.where(email: 'f@example.com')

在这里, first生成

SELECT "users".* FROM "users" WHERE "users"."email" = 'f@example.com' ORDER BY "users"."id"` ASC LIMIT 1

take生成

SELECT "users".* FROM "users" WHERE "users"."email" = 'f@example.com' LIMIT 1

如上所示,first添加了额外的排序条款。我想知道takevs之间是否存在性能差异first

take快于first还是反之亦然?

4

1 回答 1

43

一般来说,“取”会更快,因为数据库不必识别所有符合条件的行,然后对它们进行排序并找到排序最低的行。“take”允许数据库在找到单行后立即停止。

它更快的程度将根据:

  1. 不必寻找超过一排可以节省多少时间。这里最坏的情况是需要对大表进行全面扫描,但在扫描的早期就发现了一个匹配的行。“采取”将允许停止扫描。

  2. 需要对多少行进行排序才能找到具有最低 id 的行。这里最坏的情况是表中的每一行都符合条件并且需要包含在排序中。

还有一些其他因素需要考虑——例如对于“第一个”查询,优化器可能能够通过扫描主键索引来访问表并检查每一行以查看它是否符合条件。如果这种可能性非常高,那么如果查询优化器足够复杂,则可以避免对数据进行完整扫描和排序。

在许多情况下,几乎没有匹配记录和基于索引的访问来查找它们,您会发现差异是微不足道的(在您的示例中,“电子邮件”上有一个唯一索引)。但是,即使在那时,我仍然会优先使用“take”。

编辑:我只是补充一点,虽然它有点离题,但在你的例子中你不妨使用:

User.find_by(email: 'f@example.com')

生成的查询应该与 take 完全相同,但我认为语义更加清晰。

于 2013-08-28T21:11:21.997 回答