Docs 菜单

Docs 主页开发应用程序MongoDB 驱动程序Ruby MongoDB 驱动程序

查询缓存

在此页面上

  • 使用
  • 与纤程的交互
  • 查询匹配
  • 限制
  • 缓存失效
  • 手动缓存失效
  • 事务
  • 聚合(Aggregation)
  • 系统集合
  • 查询缓存中间件
  • 机架中间件
  • 活动作业中间件

MongoDB Ruby 驱动程序提供内置查询缓存。 启用后,查询缓存会保存以前执行的查找和聚合查询的结果。 当再次执行这些相同的查询时,驱动程序会返回缓存的结果,以防止不必要的数据库往返。

默认情况下,查询缓存处于禁用状态。它可以在全局范围内以及特定区块的上下文中启用。该驱动程序还提供了一个 Rack 中间件,以便为每个网络请求自动启用查询缓存。

要全局启用查询缓存:

Mongo::QueryCache.enabled = true

同样,要全局禁用它:

Mongo::QueryCache.enabled = false

要在区块上下文中启用查询缓存,请执行以下操作:

Mongo::QueryCache.cache do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
client['artists'].find(name: 'Flying Lotus').first
#=> Queries the database and caches the result
client['artists'].find(name: 'Flying Lotus').first
#=> Returns the previously cached result
end
end

要在区块上下文中禁用查询缓存,请执行以下操作:

Mongo::QueryCache.uncached do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
client['artists'].find(name: 'Flying Lotus').first
#=> Sends the query to the database; does NOT cache the result
client['artists'].find(name: 'Flying Lotus').first
#=> Queries the database again
end
end

您可以随时调用 Mongo::QueryCache.enabled?来检查是否启用了查询缓存,这将返回truefalse

查询缓存启用标志存储在纤程本地存储中(使用 Thread.current 。原则上,这允许查询缓存状态为每个纤程,尽管目前尚未测试。

Ruby 标准库中的一些方法(例如Enumerable#next 利用了纤程 在其实施中。当应用程序设置查询缓存启用标志时,这些方法不会看到该标志,因此不会使用查询缓存。例如,以下代码尽管请求了查询缓存,但并未使用它:

Mongo::QueryCache.enabled = true
client['artists'].find({}, limit: 1).to_enum.next
# Issues the query again.
client['artists'].find({}, limit: 1).to_enum.next

重写此代码以使用first而不是next会使其使用查询缓存:

Mongo::QueryCache.enabled = true
client['artists'].find({}, limit: 1).first
# Utilizes the cached result from the first query.
client['artists'].find({}, limit: 1).first

如果查询与生成缓存结果的原始查询匹配,则有资格使用缓存结果。 如果两个查询在以下值中相同,则视为匹配:

  • 命名空间(执行查询的数据库和collection)

  • 选择器(对于聚合,是聚合管道阶段)

  • 跳过

  • 排序

  • 投射

  • 排序规则

  • 读关注 (read concern)

  • 读取偏好

例如,如果您执行一个查询,然后使用不同的排序顺序执行基本相同的查询,则这些查询将不会被视为匹配,并且第二个查询不会使用第一个查询的缓存结果。

执行具有限制的查询时,查询缓存将重复使用具有较大限制的现有缓存查询(如果存在)。 例如:

Mongo::QueryCache.cache do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
client['artists'].find(genre: 'Rock', limit: 10)
#=> Queries the database and caches the result
client['artists'].find(genre: 'Rock', limit: 5)
#=> Returns the first 5 results from the cached query
client['artists'].find(genre: 'Rock', limit: 20)
#=> Queries the database again and replaces the previously cached query results
end
end

每次写入操作时,都会部分或全部清除查询缓存。 大多数写入操作会清除对正在写入的同一collection执行的任何查询的结果。某些操作会清除整个查询缓存。

以下操作将清除同一数据库和collection上缓存的查询结果(包括批量写入期间):

  • insert_one

  • update_one

  • replace_one

  • update_many

  • delete_one

  • delete_many

  • find_one_and_delete

  • find_one_and_update

  • find_one_and_replace

以下操作将清除整个查询缓存:

  • 具有$merge$out管道阶段的聚合

  • commit_transaction

  • abort_transaction

您可以随时使用以下方法清除查询缓存:

Mongo::QueryCache.clear

这将删除所有缓存的查询结果。

查询会在事务上下文中进行缓存,但在提交或中止事务时将清除整个缓存。

Mongo::QueryCache.cache do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
session = client.start_session
session.with_transaction do
client['artists'].insert_one({ name: 'Fleet Foxes' }, session: session)
client['artists'].find({}, session: session).first
#=> { name: 'Fleet Foxes' }
#=> Queries the database and caches the result
client['artists'].find({}, session: session).first
#=> { name: 'Fleet Foxes' }
#=> Returns the previously cached result
session.abort_transaction
end
client['artists'].find.first
#=> nil
# The query cache was cleared on abort_transaction
end
end

注意

事务通常以“快照(snapshot)”读关注(read concern)级别执行。请记住,具有“快照”读关注(read concern)的查询无法从没有“快照”读关注(read concern)的查询中返回缓存的结果,因此事务可能无法使用以前缓存的查询。

要了解查询何时使用缓存的结果,请参阅查询匹配部分。

查询缓存还缓存聚合管道的结果。 例如:

Mongo::QueryCache.cache do
Mongo::Client.new([ '127.0.0.1:27017' ], database: 'music') do |client|
client['artists'].aggregate([ { '$match' => { name: 'Fleet Foxes' } } ]).first
#=> Queries the database and caches the result
client['artists'].aggregate([ { '$match' => { name: 'Fleet Foxes' } } ]).first
#=> Returns the previously cached result
end
end

注意

每次写入操作期间,聚合结果都会从缓存中清除,无一例外。

MongoDB 将系统信息存储在使用database.system.*命名空间模式的collection中。这些称为系统collection。

由于应用程序未触发的活动(例如内部服务器进程)以及应用程序发出的各种数据库命令,系统collection中的数据可能会发生更改。由于很难确定系统集合的缓存结果何时过期,因此对系统集合的查询会绕过查询缓存。

您可以在MongoDB 文档中阅读有关系统集合的更多信息。

注意

即使启用了查询缓存,也不会缓存系统集合中的查询结果。

该驱动程序提供了一个 Rack 中间件,可在每个 Web 请求期间启用查询缓存。 以下示例说明了如何在 Ruby on Rails 应用程序中启用查询缓存中间件:

# config/application.rb
# Add Mongo::QueryCache::Middleware at the bottom of the middleware stack
# or before other middleware that queries MongoDB.
config.middleware.use Mongo::QueryCache::Middleware

请参阅 Rails on Rack 指南 有关在 Rails 应用程序中使用 Rack 中间件的更多信息。

该驱动程序提供了一个活动作业中间件,可为每个作业启用查询缓存。 下面的示例说明了如何在 Ruby on Rails 应用程序中启用查询缓存“活动作业”中间件:

# config/application.rb
ActiveSupport.on_load(:active_job) do
include Mongo::QueryCache::Middleware::ActiveJob
end
← 地理空间搜索
GridFS →