mongoid кеширование запросов - PullRequest
16 голосов
/ 24 мая 2011

В Rails ActiveRecord есть функция под названием Query Caching (ActiveRecord :: QueryCache), которая сохраняет результат SQL-запроса в течение всего срока действия запроса. Хотя я не очень хорошо знаком с внутренностями реализации, я думаю, что она сохраняет результаты запроса где-то в Rack env, который отбрасывается в конце запроса.

Mongoid, к сожалению, в настоящее время не предоставляет такой возможности, и это усугубляется тем фактом, что некоторые запросы происходят неявно (ссылки). Я рассматриваю возможность реализации этой функции, и мне любопытно, где и как следует подключить Mongoid (или, возможно, драйвер монго?) Для реализации этого.

Ответы [ 4 ]

13 голосов
/ 27 мая 2011

Mongoid имеет кеширование, описанное в http://mongoid.org/en/mongoid/docs/extras.html

Также у MongoDB есть возможность кеширования: http://www.mongodb.org/display/DOCS/Caching

Дополнительный модуль кэширования mongoid знает 2 различных случая: кэширование всех запросов модели или кэширование запроса.

Моноидальное кэширование работает немного по-другому: похоже, что mongoid делегирует кэширование в mongodb. (В источниках mongoid я могу найти только настройки параметров для кеширования, но без модуля кеширования.)

Напоследок скажу, что нет никакой реальной разницы в кешировании вообще - в памяти фактически находится в памяти! Неважно, в приложении или в базе данных.

Я не предпочитаю реализовывать дополнительный алгоритм кэширования, потому что он кажется избыточным и убивает ОЗУ.

Кстати: если вы действительно хотите кешировать результаты в приложении, вы можете попробовать Rails.cache или другой кеш-гем в качестве обходного пути.

7 голосов
/ 18 июня 2011

Другой ответ явно неправильный. Не только 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)
5 голосов
/ 03 июня 2015

ОК, 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}}

Источник:

Монголоидный список изменений

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

3410 Mongoid теперь имеет кеш запросов, который можно использовать в качестве промежуточного ПО в приложениях Rack. (Артур Невес)

Для рельсов:

config.middleware.use(Mongoid::QueryCache::Middleware)
3 голосов
/ 06 марта 2015

Mongoid 4.0+ теперь имеет модуль QueryCaching: http://www.rubydoc.info/github/mongoid/mongoid/Mongoid/QueryCache

Вы можете использовать его для поиска, обернув ваши поиски так:

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