Ka Mok
Ka Mok

Reputation: 1988

What is the difference between using Active Record exists? versus find_by?

In my model, I check if a Sudoku record exists in the database first before I either fetch it's solution or create it.

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

What is the difference from doing this:

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

Logs for 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)

Logs for 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)

At first, I thought by doing two find_by it would hit the database twice, but then I see the CACHE. Does that mean Rails remember the previous query in the first find_by and is only hitting it once?

Why would I use exists? over find_by ?

Edit:

From advice, I'm using this now:

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

Upvotes: 4

Views: 2480

Answers (1)

Frederick Cheung
Frederick Cheung

Reputation: 84114

Rails wraps each controller action with a simple query cache. The CACHE in the logs does indicates that the query was served from the cache. If you were to run that code in the console you wouldn't get that caching (unless you explicitly set that up).

The difference query wise is that none of the fields of the object are fetched from the database. Aside from the network impact, depending on the query and the indices present, your database may be able to use a covering index (in a nutshell the index can be used to answer the query completely instead of the db using the index to find the data for the row)

On top of that rails doesn't construct an active record object from the result, you just get back true/false.

So exists? is faster. However it's pointless if you then call find_by straight after. You might as well call find_by once only.

Upvotes: 9

Related Questions