Ruby的.where vs.detect

Syl*_*lar 4 ruby activerecord ruby-on-rails

我正在寻找一种更快,使用更少服务器处理的方法。在我的应用程序中,我可以同时使用.where.detect

哪里:

User.where(id: 1)
# User Load (0.5ms)
Run Code Online (Sandbox Code Playgroud)

检测:

User.all.detect{ |u| u.id == 1 }
# User Load (0.7ms). Sometimes increases more than .where
Run Code Online (Sandbox Code Playgroud)

我了解这会.detect 返回列表中该块返回TRUE的第一项,但是.where如果我有成千上万个Users ,它将与之相比如何?

为清楚起见进行了编辑。

.where在此示例中使用,因为我可能不会id单独查询。如果我有一个名为“名称”的表列怎么办?

spi*_*ann 5

在这个例子中

User.find(1)        # or
User.find_by(id: 1)
Run Code Online (Sandbox Code Playgroud)

将是最快的解决方案。因为这两个查询都告诉数据库返回一个完全匹配的记录id。一旦数据库找到匹配的记录,它就不会再查找,而是立即返回该记录。

鉴于

User.where(id: 1)
Run Code Online (Sandbox Code Playgroud)

将返回匹配条件的对象数组。这意味着:找到匹配的记录后,数据库将继续查找其他记录以匹配查询,因此始终扫描整个数据库表。在这种情况下(由于id很有可能是一列具有唯一值的列),它将返回仅包含一个实例的数组。

在对面

User.all.detect { |u| u.id == 1 }
Run Code Online (Sandbox Code Playgroud)

从数据库中加载所有用户。这将导致成千上万的用户加载到内存中,构建ActiveRecord实例,遍历该数组,然后丢弃所有不符合条件的记录。与仅从数据库加载匹配的记录相比,这将非常慢。

数据库管理系统已针对运行选择查询进行了优化,您可以通过设计有用的架构并添加适当的索引来提高数据库管理系统的能力。从数据库加载的每个记录都需要转换为ActiveRecord实例,并且会占用内存-两种操作都不是免费的。因此,经验法则应该是:只要有可能,就直接在数据库中而不是在Ruby中运行查询。