以及在Ruby on Rails中的首次演出

时间:2013-08-28 19:16:59

标签: sql ruby-on-rails activerecord ruby-on-rails-4

这是关于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增加了额外的排序条款。我想知道takefirst之间是否存在性能差异。

takefirst快,反之亦然?

1 个答案:

答案 0 :(得分:34)

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

它的快速程度将根据以下情况而变化:

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

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

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

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

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

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

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