Skip to main content

Targeted Queries | Shards | MongoDB | Banco de dados

  • Targeted Queries | Shards | MongoDB | Banco de dados

Targeted queries no MongoDB

Targeted queries são consultas que, em um cluster sharded, conseguem ser roteadas pelo mongos para um shard específico ou para um conjunto pequeno de shards.

Isso acontece quando a query usa a shard key no filtro, principalmente quando usa o prefixo da shard key composta.

Em sharding, o mongos é o roteador da consulta. Ele analisa o filtro da query e decide para quais shards a operação precisa ser enviada. O tema aparece dentro de sharding como parte de “querying sharded data”, “query router” e escolha correta da shard key.


Exemplo com shard key simples

sh.shardCollection("loja.pedidos", { clienteId: 1 })

Query targeted:

db.pedidos.find({
clienteId: 123
})

Aqui o MongoDB consegue rotear a consulta usando clienteId, que é a shard key.

Query não targeted:

db.pedidos.find({
status: "PENDENTE"
})

Como status não é a shard key, o mongos não sabe em qual shard procurar. Então ele pode consultar todos os shards. Isso é chamado de scatter-gather.


Shard key composta

info

Se no método find() as shards key estiverem invertidas, mas conterem todas, o mongo reorganiza e é uma boa query

{ "airline_id" : 1, "departure_airport" : 1 }

db.flights.find( { airline_id: 2946863 } )
db.flights.find( { departure_airport: "JFK", airline_id: 2946863 } )
db.flights.find( { airline_id: 2946863, departure_airport: "JFK" } )

Uma shard key composta usa mais de um campo para distribuir os documentos.

Exemplo:

sh.shardCollection("loja.pedidos", {
clienteId: 1,
dataPedido: 1
})

Aqui a shard key é composta por:

clienteId + dataPedido

A ordem importa.

O primeiro campo, clienteId, é o prefixo da shard key.


Exemplo 1: usando o primeiro campo da shard key

db.pedidos.find({
clienteId: 123
})

Essa query tende a ser targeted, porque usa o primeiro campo da shard key composta.

Mesmo sem informar dataPedido, o MongoDB já consegue restringir a busca aos chunks relacionados ao clienteId.


Exemplo 2: usando a shard key completa

db.pedidos.find({
clienteId: 123,
dataPedido: ISODate("2026-05-21")
})

Essa é ainda melhor.

Aqui a query usa os dois campos da shard key:

clienteId + dataPedido

O mongos consegue rotear a consulta com mais precisão.


Exemplo 3: usando range no segundo campo

db.pedidos.find({
clienteId: 123,
dataPedido: {
$gte: ISODate("2026-05-01"),
$lt: ISODate("2026-06-01")
}
})

Também pode ser targeted, porque usa o prefixo clienteId.

O segundo campo, dataPedido, ajuda a limitar ainda mais a busca.


Exemplo 4: usando apenas o segundo campo

db.pedidos.find({
dataPedido: ISODate("2026-05-21")
})

Essa query não é boa para roteamento.

Mesmo dataPedido fazendo parte da shard key, ele não é o primeiro campo. Como a shard key é:

{
clienteId: 1,
dataPedido: 1
}

o MongoDB precisa primeiro de clienteId para conseguir rotear bem.

Ou seja: usar apenas dataPedido pode virar scatter-gather.


Exemplo 5: shard key composta com região e cliente

sh.shardCollection("loja.pedidos", {
regiao: 1,
clienteId: 1
})

Boa query:

db.pedidos.find({
regiao: "SP"
})

Targeted ou parcialmente targeted, porque usa o primeiro campo da shard key.

Melhor query:

db.pedidos.find({
regiao: "SP",
clienteId: 123
})

Mais precisa, porque usa a shard key completa.

Query ruim:

db.pedidos.find({
clienteId: 123
})

Apesar de clienteId fazer parte da shard key, ele não é o primeiro campo. Como falta regiao, o roteamento fica pior.


Exemplo 6: shard key composta com tenant

Muito comum em sistemas multi-tenant:

sh.shardCollection("app.eventos", {
tenantId: 1,
criadoEm: 1
})

Boa query:

db.eventos.find({
tenantId: "empresa-001"
})

Melhor:

db.eventos.find({
tenantId: "empresa-001",
criadoEm: {
$gte: ISODate("2026-05-01"),
$lt: ISODate("2026-06-01")
}
})

Ruim:

db.eventos.find({
criadoEm: {
$gte: ISODate("2026-05-01")
}
})

Sem tenantId, o MongoDB pode precisar consultar vários shards.


Resumo prático

QueryShard keyTargeted?Motivo
{ clienteId: 123 }{ clienteId: 1 }SimUsa a shard key
{ status: "PENDENTE" }{ clienteId: 1 }NãoNão usa a shard key
{ clienteId: 123 }{ clienteId: 1, dataPedido: 1 }SimUsa o prefixo da shard key
{ clienteId: 123, dataPedido: ... }{ clienteId: 1, dataPedido: 1 }SimUsa a shard key completa
{ dataPedido: ... }{ clienteId: 1, dataPedido: 1 }Geralmente nãoNão usa o prefixo inicial
{ regiao: "SP" }{ regiao: 1, clienteId: 1 }SimUsa o primeiro campo
{ clienteId: 123 }{ regiao: 1, clienteId: 1 }Geralmente nãoPula o primeiro campo

Regra de ouro

Para uma query ser bem direcionada em shard key composta, ela deve usar o primeiro campo da shard key.

Shard key composta:
{ A: 1, B: 1, C: 1 }

Boas queries:
{ A: ... }
{ A: ..., B: ... }
{ A: ..., B: ..., C: ... }

Queries ruins para roteamento:
{ B: ... }
{ C: ... }
{ B: ..., C: ... }

Ou seja:

Tem o prefixo da shard key = tende a ser targeted
Não tem o prefixo da shard key = tende a ser scatter-gather