Кэширование запросов mongoid
В Rails ActiveRecord есть функция, называемая Query Caching (ActiveRecord:: QueryCache), которая сохраняет результат SQL-запроса для срока службы запроса. Хотя я не очень хорошо знаком с внутренними реализациями, я думаю, что он сохраняет результаты запроса где-то в Rack env, который отбрасывается в конце запроса.
Монгоид, к сожалению, в настоящее время не предоставляет такую функцию, и это усугубляется тем фактом, что некоторые запросы происходят неявно (ссылки).
Я планирую реализовать эту функцию, и мне любопытно, где и как следует использовать Mongoid (или, возможно, драйвер mongo?), Чтобы реализовать это.
Ответы
Ответ 1
Другой ответ явно ошибочен. Не только mongoid или mongo драйвер не кэширует запрос, даже если mongo будет - он все еще может быть на другой машине по сети.
Моим решением было обернуть get_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)
Ответ 2
У Mongoid есть кеширование, описанное в http://mongoid.org/en/mongoid/docs/extras.html
Также у MongoDB есть способность кэширования: http://www.mongodb.org/display/DOCS/Caching
Мангоидное кэширование дополнительно знает 2 разных случая: кэширование всех запросов модели или кэширование запроса.
Монгоидное кэширование работает несколько иначе: он похож на мангоидных делегатов, кэширующих mongodb. (В источниках mongoid я могу найти параметры параметров для кеширования, но не модуль кеширования.)
Наконец, скажем, нет никакой реальной разницы в кэшировании вообще - в памяти действительно есть память! Независимо от того, находится ли это в приложении или в базе данных.
Я не предпочитаю реализовывать дополнительный алгоритм кеширования, потому что это кажется избыточным и убийцей RAM.
BTW: Если вы действительно хотите кэшировать результаты в приложении, вы можете попробовать Rails.cache или другой кеш-камень в качестве обходного пути.
Ответ 3
ОК, 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. (Артур Невес)
Для Rails:
config.middleware.use(Mongoid::QueryCache::Middleware)
Ответ 4
В Mongoid 4.0+ теперь есть модуль QueryCaching: http://www.rubydoc.info/github/mongoid/mongoid/Mongoid/QueryCache
Вы можете использовать его для находок, обернув ваши запросы следующим образом:
QueryCache.cache { MyCollection.find("xyz") }