Raphael
Raphael

Reputation: 1721

Strange Performance issues with where() vs find()

Mongoid 3.1.6 Rails 3.2.21 MongoDB 2.4.9

We're seeing strange performance issues with find() vs where().first:

$ rails c
2.1.5 :001 > Benchmark.ms { User.find('5091e4beccbce30200000006') }
 => 7.95 
2.1.5 :002 > Benchmark.ms { User.find('5091e4beccbce30200000006') }
 => 0.27599999999999997 
2.1.5 :003 > Benchmark.ms { User.find('5091e4beccbce30200000006') }
 => 0.215 
2.1.5 :004 > exit

$ rails c
2.1.5 :001 > Benchmark.ms { User.where(id: '5091e4beccbce30200000006').first }
 => 7.779999999999999 
2.1.5 :002 > Benchmark.ms { User.where(id: '5091e4beccbce30200000006').first }
 => 4.84 
2.1.5 :003 > Benchmark.ms { User.where(id: '5091e4beccbce30200000006').first }
 => 5.297 
2.1.5 :004 > exit

These both appear to be firing off the same queries. Can someone explain why we're seeing such a huge difference in performance?

Configuration:

production:
  sessions:
    default:
      uri: <%= REDACTED %>
      options:
        consistency: :strong
        safe: true
        max_retries: 1
        retry_interval: 0
  options:
    identity_map_enabled: true

Upvotes: 4

Views: 539

Answers (2)

Raphael
Raphael

Reputation: 1721

It appears that find uses the identity map, while where does not. If I set identity_map_enabled to false, then the performance of find vs where is identical.

Moral of the story: use find instead of where when possible.

I've heard that the identity map is removed in Mongoid 4.x. So maybe this issue only affects folks on older versions.

Upvotes: 0

Salvador Dali
Salvador Dali

Reputation: 222979

Here is my assumption why the first one was few orders of magnitude slower (I am writing it from mongo point of view and have zero knowledge about ruby).

The first time you fired the query it was not in the working set and this caused slower performance. The consecutive times it was already there and thus performance is better. If you have small number of documents, I would find this behavior strange (because I would expect that all of them would be in a working set).

The second part with $where surprises me because I would expect all the numbers be bigger than with find() (it is not the case with the first event) because:

The $where provides greater flexibility, but requires that the database processes the JavaScript expression or function for each document in the collection.

Upvotes: 0

Related Questions