本文介绍了在 Ruby on Rails 中进行与首次性能对比的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This is a question regarding ActiveRecord query methods:

  • first 查找第一条记录(如果提供了参数,则查找前 N 条记录).如果未定义顺序,则将按主键排序.
  • take 给出一条记录(如果提供了参数,则给出 N 条记录),没有任何隐含的顺序.顺序将取决于数据库实现.如果提供订单,我们将予以遵守.
  • first Find the first record (or first N records if a parameter is supplied). If no order is defined it will order by primary key.
  • take Gives a record (or N records if a parameter is supplied) without any implied order. The order will depend on the database implementation. If an order is supplied it will be respected.

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

usecase:retrieve record from database based on unique attribute, example.

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

这里,生成

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 之间是否存在性能差异.

so as seen above first adds additional ordering clause. I am wondering if there a performance difference between take vs first.

take 是否比 first 快,反之亦然?

Is take faster than first or vice-versa?

推荐答案

一般情况下take"会更快,因为数据库不必识别所有符合条件的行然后对它们进行排序并找到最低的-排序行.take"允许数据库在找到一行后立即停止.

In general "take" will be faster, because the database does not have to identify all of the rows that meet the criteria and then sort them and find the lowest-sorting row. "take" allows the database to stop as soon as it has found a single row.

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

The degree to which it is faster is going to vary according to:

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

  1. How much time is saved in not having to look for more than one row. The worst case here is where a full scan of a large table is required, but one matching row is found very early in the scan. "take" would allow the scan to be stopped.

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

How many rows would need to be sorted to find the one with the lowest id. The worst case here is where every row in the table matches the criteria and needs to be included in the sort.

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

There are some other factors to consider -- for example for a "first" query the optimiser might be able to access the table via a scan of the primary key index and check each row to see if it matches the condition. If there is a very high likelihood of that then both a complete scan of the data and a sort can be avoided if the query optimiser is sophisticated enough.

在许多情况下,匹配记录很少,并且可以通过基于索引的访问来查找它们,您会发现差异很小(在您的示例中,电子邮件"上有一个唯一索引).但是,即使那样,我仍然会优先使用take"而不是 first.

In many cases, where there are very few matching records and index-based access to find them, you'll find that the difference is trivial (where there is a unique index on "email" in your example). However, I would still use "take" in preference to first even then.

我会补充一点,虽然它有点跑题,但在您的示例中您不妨使用:

I'll just add, though it's a little off-topic, that in your example you might as well use:

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

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

The generated query should be exactly the same as for take, but the semantics are a bit more clear I think.

这篇关于在 Ruby on Rails 中进行与首次性能对比的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 03:42
查看更多