Cache de consulta
Nesta página
O driver Ruby do MongoDB fornece um cache de query integrado. Quando ativado, o cache de query salva os resultados das querys de busca e agregação executadas anteriormente. Quando essas mesmas query são realizadas novamente, o driver retorna os resultados em cache para evitar viagens de ida e volta desnecessárias ao reconhecimento de data center.
Uso
O cache de query está desabilitado por padrão. Ele pode ser habilitado no escopo global, bem como dentro do contexto de um bloco específico. O driver também fornece um middleware Rack para ativar o cache de query automaticamente para cada solicitação da web.
Para habilitar o cache de query globalmente:
Mongo::QueryCache.enabled = true
Da mesma forma, para desativá-lo globalmente:
Mongo::QueryCache.enabled = false
Para habilitar o cache de query no contexto de um bloqueio:
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
E para desabilitar o cache de query no contexto de um bloco:
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
Você pode verificar se o cache de query está habilitado a qualquer momento ligando para Mongo::QueryCache.enabled?
, que retornará true
ou false
.
Interações com Fibras
O sinalizador de ativação do cache de query é armazenado no armazenamento local de Fibra (usando Thread.current . Isso, em princípio, permite que o estado do cache de query seja por camada, embora isso não seja testado atualmente.
Existem métodos na biblioteca padrão Ruby, como Enumerable#next
, que utilizam limitações em sua implementação. Esses métodos não viam o sinalizador de ativação do cache de query quando ele era definido pelos aplicativos e, subsequentemente, não usavam o cache de query. Por exemplo, o código a seguir não utiliza o cache de query, apesar de solicitá-lo:
Mongo::QueryCache.enabled = true client['artists'].find({}, limit: 1).to_enum.next # Issues the query again. client['artists'].find({}, limit: 1).to_enum.next
Reescrever este código para utilizar first
em vez de next
faria com que ele utilizasse o cache de query:
Mongo::QueryCache.enabled = true client['artists'].find({}, limit: 1).first # Utilizes the cached result from the first query. client['artists'].find({}, limit: 1).first
Correspondência de query
Uma query será elegível para usar resultados em cache se corresponder à query original que produz os resultados em cache. Duas query são consideradas correspondentes se forem idênticas nos seguintes valores:
namespace (o reconhecimento de data center e a collection na qual a query foi realizada)
Seletor (para agregações, os estágios do pipeline de agregação)
Ignorar
Sort
Projeção
Agrupamentos
Preocupação de leitura
readPreference
Por exemplo, se você executar uma query e, em seguida, executar uma query quase idêntica com uma ordem de classificação diferente, essas queries não serão consideradas correspondentes e a segunda query não usará os resultados em cache da primeira.
Limites
When performing a query with a limit, the query cache will reuse an existing cached query with a larger limit if one exists. Por exemplo:
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
Invalidação de cache
O cache de query é limpo em parte ou totalmente em cada operação de gravação. A maioria das operações de gravação limpará os resultados de qualquer query que foram realizadas na mesma collection em que está sendo gravada. Algumas operações limparão todo o cache de query.
As operações a seguir limparão os resultados da query em cache no mesmo reconhecimento de data center e collection (inclusive durante gravações em massa):
insert_one
update_one
replace_one
update_many
delete_one
delete_many
find_one_and_delete
find_one_and_update
find_one_and_replace
As operações a seguir limparão todo o cache de query:
agregação com estágios de pipeline
$merge
ou$out
commit_transaction
abort_transaction
Invalidação de cache manual
Você pode limpar o cache da query a qualquer momento com o método a seguir:
Mongo::QueryCache.clear
Isso removerá todos os resultados de query em cache.
Transações
As query são armazenadas em cache dentro do contexto de uma transação, mas todo o cache será limpo quando a transação for confirmada ou cancelada.
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
Observação
As transações geralmente são realizadas com um nível de referência de leitura "snapshot". Lembre-se de que uma query com uma referência de leitura "snapshot" não pode retornar resultados em cache de uma query sem a referência de leitura "snapshot", portanto, é possível que uma transação não use query em cache anteriormente.
Para entender quando uma query usará um resultado em cache, consulte a seção Correspondência de query .
Agregações
O cache de query também armazena em cache os resultados de pipelines de agregação. Por exemplo:
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
Observação
Os resultados da agregação são limpos do cache durante cada operação de gravação, sem exceções.
Coleções do sistema
O MongoDB armazena informações do sistema em collection que usam o padrão de namespace database.system.*
. Essas são chamadas de collection do sistema.
Os dados na collection do sistema podem ser alterados devido a atividades não acionadas pela aplicação (como processos internos do servidor) e como resultado de um reconhecimento de data center emitidos pela aplicação. Devido à dificuldade de determinar quando os resultados em cache para collection do sistema devem ser expirados, as query nas collection do sistema ignoram o cache de consulta.
Você pode ler mais sobre collections do sistema na documentação do MongoDB.
Observação
Mesmo quando a query estiver habilitada, os resultados da query da collection do sistema não serão armazenados em cache.
Middleware de cache de query
Middleware de rack
O driver fornece um middleware Rack que habilita o cache de query para a duração de cada solicitação da web. Abaixo está um exemplo de como habilitar o middleware de cache de query em uma aplicação 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
Consulte o guia Rails on Rack para obter mais informações sobre como usar o middleware Rack em aplicativos Rails.
Middleware de tarefa ativo
O driver fornece um middleware de tarefa ativa que habilita o cache de query para cada tarefa. Abaixo está um exemplo de como habilitar o middleware de tarefa Active Job de cache de query em uma aplicação Ruby on Rails:
# config/application.rb ActiveSupport.on_load(:active_job) do include Mongo::QueryCache::Middleware::ActiveJob end