where() 与 find() 的奇怪性能问题

Strange Performance issues with where() vs find()

Mongoid 3.1.6 Rails 3.2.21 MongoDB2.4.9

我们发现 find()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

这两个似乎都触发了相同的查询。谁能解释一下为什么我们看到如此巨大的性能差异?

配置:

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

这是我的假设,为什么第一个要慢几个数量级(我是从 mongo 的角度写的,对 ruby 的了解为零)。

您第一次启动查询时,它不在工作集中,这导致性能下降。它已经存在的连续时间因此性能更好。如果您的文档数量很少,我会发现这种行为很奇怪(因为我希望所有文档都在一个工作集中)。

$where 的第二部分让我感到惊讶,因为我希望所有数字都比 find() 大(第一个事件不是这种情况),因为:

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

似乎 find 使用恒等映射,而 where 不使用。如果我将 identity_map_enabled 设置为 false,那么 findwhere 的性能是相同的。

故事的寓意:尽可能使用 find 而不是 where

我听说在 Mongoid 中删除了标识映射 4.x。所以也许这个问题只影响旧版本的人。