查询缓存
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?
来检查是否启用了查询缓存,这将返回true
或false
。
与纤程的交互
查询缓存启用标志存储在纤程本地存储中(使用 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)
选择器(对于聚合,是聚合管道阶段)
跳过
Sort
投射
排序规则
读关注 (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)的查询中返回缓存的结果,因此事务可能无法使用以前缓存的查询。
要了解查询何时使用缓存的结果,请参阅查询匹配部分。
聚合(Aggregation)
查询缓存还缓存聚合管道的结果。 例如:
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中的数据可能会发生更改。由于很难确定系统集合的缓存结果何时过期,因此对系统集合的查询会绕过查询缓存。
注意
即使启用了查询缓存,也不会缓存系统集合中的查询结果。
查询缓存中间件
机架中间件
该驱动程序提供了一个 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