使用 Active Record 存在什么区别?与 find_by 相比?

Ka *_*Mok 4 ruby activerecord ruby-on-rails

在我的模型中,我首先检查Sudoku数据库中是否存在记录,然后再获取它solution或创建它。

if Sudoku.exists?(puzzle: puzzle)
  return Sudoku.find_by(puzzle: puzzle).solution
else
  **solve it and save it into the db**
end
Run Code Online (Sandbox Code Playgroud)

这样做有什么区别:

if Sudoku.find_by(puzzle: puzzle)
  return Sudoku.find_by(puzzle: puzzle).solution
else
  **solve it and save it into the db**
end
Run Code Online (Sandbox Code Playgroud)

日志 exists?

Sudoku Exists (0.0ms)  SELECT  1 AS one FROM "sudokus" WHERE "sudokus"."puzzle" = $1 LIMIT 1  [["puzzle", "390820700801500069020160403002096058935000602060752030703941000200037590019000347"]]
  Sudoku Load (0.0ms)  SELECT  "sudokus".* FROM "sudokus" WHERE "sudokus"."puzzle" = $1 LIMIT 1  [["puzzle", "390820700801500069020160403002096058935000602060752030703941000200037590019000347"]]
Completed 200 OK in 8ms (Views: 0.2ms | ActiveRecord: 3.0ms)
Run Code Online (Sandbox Code Playgroud)

日志 find_by

 Sudoku Load (0.0ms)  SELECT  "sudokus".* FROM "sudokus" WHERE "sudokus"."puzzle" = $1 LIMIT 1  [["puzzle", "390820700801500069020160403002096058935000602060752030703941000200037590019000347"]]
  CACHE (0.0ms)  SELECT  "sudokus".* FROM "sudokus" WHERE "sudokus"."puzzle" = $1 LIMIT 1  [["puzzle", "390820700801500069020160403002096058935000602060752030703941000200037590019000347"]]
Completed 200 OK in 7ms (Views: 0.2ms | ActiveRecord: 2.0ms)
Run Code Online (Sandbox Code Playgroud)

起初,我认为通过执行两次find_by它会两次访问数据库,但后来我看到了缓存。这是否意味着 Rails 会记住第一个查询中的前一个查询find_by并且只命中一次?

我为什么要使用exists?over find_by

编辑:

根据建议,我现在正在使用它:

if sudoku = Sudoku.find_by(puzzle: puzzle)
  return sudoku.solution
else
  **solve it and save it into the db**
end
Run Code Online (Sandbox Code Playgroud)

Fre*_*ung 6

Rails 用一个简单的查询缓存包装每个控制器操作。在CACHE日志中确实表明查询是从缓存中。如果您要在控制台中运行该代码,则不会获得该缓存(除非您明确设置)。

不同的查询方式是没有从数据库中获取对象的任何字段。除了网络影响之外,根据查询和存在的索引,您的数据库可能能够使用覆盖索引(简而言之,索引可用于完全回答查询,而不是使用索引查找数据的数据库为行)

最重要的是,rails 不会根据结果构造活动记录对象,您只会返回 true/false。

所以exists?更快。但是,如果您随后find_by直接拨打电话,则毫无意义。你也可以find_by只调用一次。