Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 以Ruby on Rails中的vs first性能为例_Sql_Ruby On Rails_Activerecord_Ruby On Rails 4 - Fatal编程技术网

Sql 以Ruby on Rails中的vs first性能为例

Sql 以Ruby on Rails中的vs first性能为例,sql,ruby-on-rails,activerecord,ruby-on-rails-4,Sql,Ruby On Rails,Activerecord,Ruby On Rails 4,这是一个关于ActiveRecord查询方法的问题: first查找第一条记录(如果提供了参数,则查找前N条记录)。如果未定义订单,它将按主键进行订单 take给出一条记录(如果提供了参数,则为N条记录),但没有任何隐含顺序。顺序将取决于数据库实现。如果提供订单,则将遵守该订单 用例: 例如,根据唯一属性从数据库检索记录 User.where(email: 'f@example.com') 这里,, 首先生成 SELECT "users".* FROM "users" WHERE "use

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

  • first
    查找第一条记录(如果提供了参数,则查找前N条记录)。如果未定义订单,它将按主键进行订单
  • take
    给出一条记录(如果提供了参数,则为N条记录),但没有任何隐含顺序。顺序将取决于数据库实现。如果提供订单,则将遵守该订单
用例: 例如,根据唯一属性从数据库检索记录

User.where(email: 'f@example.com')
这里,,
首先生成

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

SELECT "users".* FROM "users" WHERE "users"."email" = 'f@example.com' ORDER BY "users"."id"` ASC LIMIT 1
SELECT "users".* FROM "users" WHERE "users"."email" = 'f@example.com' LIMIT 1
因此,如上所述,
first
添加了额外的排序子句。我想知道
take
first
之间是否存在性能差异

take
first
快吗?反之亦然?

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

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

  • 不必查找多行可以节省多少时间。这里最糟糕的情况是需要对一个大表进行完整扫描,但在扫描的很早就找到了一个匹配的行。“take”将允许停止扫描

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

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

    在许多情况下,如果匹配记录和基于索引的访问很少,您会发现差异很小(在您的示例中,“email”上有一个唯一的索引)。然而,即使在那时,我仍然会优先使用“take”而不是first

    编辑:我只想补充一点,尽管这有点离题,在您的示例中,您最好使用:

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

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

    您需要订单吗?不,我更关心性能。但如果两者的性能相同,那么我将使用
    。首先,在可能需要或不需要订单的任何地方使用
    ,因为它很容易记住。这就是为什么这个提问会更快的原因,因为它不包含order子句,但我假设差异可以忽略不计。一种方法是:基准测试。注意,
    User.find\u by\u email('f@example.com)
    ?这将生成与
    take
    相同的查询。