mongoid查询缓存



Rails的ActiveRecord有一个名为Query Caching(ActiveRecord::QueryCache)的功能,它在请求的生存期内保存SQL查询的结果。虽然我不太熟悉实现的内部结构,但我认为它将查询结果保存在Rack env中的某个位置,该位置在请求结束时被丢弃。

不幸的是,Mongoid目前没有提供这样的功能,而且一些查询是隐式发生的(引用),这一事实加剧了这种情况。我正在考虑实现这个功能,我很好奇Mongoid(或者,也许是mongo驱动程序?)应该在哪里以及如何挂钩才能实现这个功能。

Mongoid有缓存,在http://mongoid.org/en/mongoid/docs/extras.html

MongoDB本身也具有缓存能力:http://www.mongodb.org/display/DOCS/Caching

mongoid缓存额外知道两种不同的情况:缓存模型的所有查询或缓存查询。

Mongoid缓存的工作方式似乎略有不同:它看起来像是Mongoid将缓存委托给mongodb。(在mongoid的来源中,我只能找到缓存的选项设置,但没有缓存模块。)

最后要说的是,缓存在一般情况下并没有真正的区别——内存实际上就是内存!无论它是在应用程序中还是在数据库中。

我不喜欢实现额外的缓存算法,因为这似乎是多余的,而且是RAM杀手。

BTW:如果你真的想在应用程序中缓存结果,你可以尝试Rails.cache或其他缓存宝石作为解决方法。

另一个答案显然是错误的。不仅mongoid或mongo驱动程序不缓存查询,即使mongo会缓存查询,它也可能在网络上的其他机器上。

我的解决方案是将receive_message封装在Mongo::Connection中。优点:一个确定的地方缺点:反序列化仍在进行


require 'mongo'
module Mongo
  class Connection
    module QueryCache
      extend ActiveSupport::Concern
      module InstanceMethods
        # Enable the selector cache within the block.
        def cache
          @query_cache ||= {}
          old, @query_cache_enabled = @query_cache_enabled, true
          yield
        ensure
          clear_query_cache
          @query_cache_enabled = old
        end
        # Disable the selector cache within the block.
        def uncached
          old, @query_cache_enabled = @query_cache_enabled, false
          yield
        ensure
          @query_cache_enabled = old
        end
        def clear_query_cache
          @query_cache.clear
        end
        def cache_receive_message(operation, message)
          @query_cache[operation] ||= {}
          key = message.to_s.hash
          log = "[MONGO] CACHE %s"
          if entry = @query_cache[operation][key]
            Mongoid.logger.debug log % 'HIT'
            entry
          else
            Mongoid.logger.debug log % 'MISS'
            @query_cache[operation][key] = yield
          end
        end
        def receive_message_with_cache(operation, message, log_message=nil, socket=nil, command=false)
          if query_cache_enabled
            cache_receive_message(operation, message) do
              receive_message_without_cache(operation, message, log_message, socket, command)
            end
          else
            receive_message_without_cache(operation, message, log_message, socket, command)
          end
        end
      end # module InstanceMethods
      included do
        alias_method_chain :receive_message, :cache
        attr_reader :query_cache, :query_cache_enabled
      end
    end # module QueryCache
  end # class Connection
end
Mongo::Connection.send(:include, Mongo::Connection::QueryCache)

OK,Mongoid 4支持QueryCache中间件。

只需在application.rb 中添加中间件

config.middleware.use "Mongoid::QueryCache::Middleware"

然后获利:

  MOPED: 127.0.0.1:27017 QUERY        database=XXX collection=page_variants selector={"$query"=>{"_id"=>BSON::ObjectId('5564dabb6d61631e21d70000')}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil runtime: 0.4397ms
  MOPED: 127.0.0.1:27017 QUERY        database=XXX collection=page_variants selector={"$query"=>{"_id"=>BSON::ObjectId('5564dacf6d61631e21dc0000')}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil runtime: 0.4590ms
  QUERY CACHE                         database=XXX collection=page_variants selector={"$query"=>{"_id"=>BSON::ObjectId('5564c9596d61631e21d30000')}, "$orderby"=>{:_id=>1}}
  QUERY CACHE                         database=XXX collection=page_variants selector={"$query"=>{"_id"=>BSON::ObjectId('5564dabb6d61631e21d70000')}, "$orderby"=>{:_id=>1}}

来源:

Mongoid变更日志

https://github.com/mongoid/mongoid/blob/master/CHANGELOG.md#new-功能-2

3410 Mongoid现在有一个查询缓存,可以用作Rack应用程序中的中间件。(阿瑟·内维斯)

轨道:

config.middleware.use(Mongoid::QueryCache::Middleware)

Mongoid 4.0+现在有一个QueryCaching模块:http://www.rubydoc.info/github/mongoid/mongoid/Mongoid/QueryCache

您可以在查找中使用它,方法是这样包装查找:

QueryCache.cache { MyCollection.find("xyz") }

相关内容

  • 没有找到相关文章

最新更新