在Ruby on Rails中采取vs首次演出

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

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

usecase:基于唯一属性从数据库中检索记录,例如。

 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添加额外的排序条款。 我想知道take vs first之间是否存在性能差异。

first take快,反之亦然?

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

它的快速程度将根据以下因素而变化:

  1. 在不必查找多行的情况下节省了多少时间。 这里最糟糕的情况是需要对大型表进行全扫描,但在扫描的早期就会发现一个匹配的行。 “take”将允许扫描停止。

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

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

在许多情况下,只有很少的匹配记录和基于索引的访问权限才能找到它们,您会发现差异很小(在您的示例中“电子邮件”中有唯一索引)。 但是,即便如此,我仍然会优先使用“take”。

编辑:我只是添加,虽然它有点偏离主题,但在您的示例中,您可以使用:

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

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