Armazenamento e consultas em grande volume de dados com flexibilidade e performance.
Objetivo: Uma visão geral sobre funcionalidades, particularidades e
performance.
Leonardo Loures Quirino
Desenvolvedor Java na Bematech desde 2014.
twitter: @LeonrdQrn
Tópicos
Introdução ao MongoDBManipulação de dadosPerformanceRéplicasShardingFramework de AgregaçãoFrameworks Java
Introdução ao MongoDB
Banco de dados não relacional
Orientado a documentos
Schema flexível
Open Source
Introdução ao MongoDB
Documentos word??? Não!
Documentos JSONEx:
{ “a” : 6,"b” : “teste”,“frutas” : [“maçã”, “uva”]
}
Introdução ao MongoDB
Flexibilidade:
Requisitos
Soluções incrementais
Melhorias e evoluções
Performance horizontalmente escalável
Sem suporte a joins
Sem suporte a transações
Performance x funcionalidade
Introdução ao MongoDB
Relacional MongoDatabase Database
tabela coleçõesíndice índicelinha documento
coluna campojoin agrupamento & ligações
Introdução ao MongoDB
Exemplos de utilização
● ticketmaster ● EA ● SquareEnix● Google ● Cisco ● ebay● facebook ● Foursquar
e
Manipulação de dados
BSON - Binary JSON
Superset de JSON
Saiba mais: http://bsonspec.org/
Manipulação de dados
CRUD:
Insert
Find
Remove
Update
Inserindo um documento
> doc = {“nome” : “Leonardo Quirino”,“idade” : “30”,
profissão” : “Desenvolvedor”}
> db.pessoas.insert ( doc )
Procurando documentos
> db.pessoas.findOne( ) ou db.pessoas.find( )
{ “_id” : ObjectId("507f1f77bcf86cd799439011"), “nome” : ”Leonardo Quirino”, “idade” : 30, “profissão” : “Desenvolvedor”
}
Procurando documentos
O campo _id
Análogo à chave primária no modelo relacional
Campo obrigatório
Valor único dentro da coleção
Valor imutávelPode ser um documento
Ex:“_id” : { “nome” : Fulano, “sobrenome” : “de tal” }
Procurando documentos
Os métodos de busca aceitam parâmetros para realizar as buscas.Primeiro argumento : FiltrosSegundo argumento : Modelo a ser retornado> db.pessoas.findOne( { “nome” : “Leonardo Quirino” } , { “nome” : true } )
{ “_id” : ObjectId("....") , “nome” : ”Leonardo Quirino” }
> db.pessoas.findOne( { “nome” : “Leonardo Quirino” } , { “nome” : true , “_id” : false } )
{ “nome” : ”Leonardo Quirino” }
Procurando documentos
Operadores$gt e $lt / $gte e $lte
Ex: > db.notas.find({“nota” : {$gt : 60 }})
$existsEx: > db.pessoas.find({“profissão” : {$exists : true }})
$typeEx: > db.pessoas.find({“nome” : {$type : 2 }})
https://docs.mongodb.org/manual/reference/bson-types/
$regexEx: > db.pessoas.find({“nome” : {$regex : “o$” }})
Operadores$or
Ex: > db.pessoas.find ({ $or : [{ “nome" : “Leonardo Quirino” },{ “profissão” : “Desenvolvedor” }
] } )
$andEx: > db.pessoas.find ({ $and : [
{ “nome" : “Leonardo Quirino” },{ “profissão” : “Desenvolvedor” }
] } )
Procurando documentos
> db.notas.find ( {“nota” : { $gt : 50 },“nota” : { $lt : 60 }
} );
[ ] Encontra todos os documentos com nota entre 50 e 60[ ] Encontra todos os documentos com nota maior que 50[ ] Encontra todos os documentos com nota menor que 60[ ] Nenhuma das opções
Pergunta
X
Queries em arrays
Se quisermos buscar valores dentro de arrays?
{ “_id” : ObjectId("507f1f77bcf86cd799439011"), “nome” : ”Leonardo Quirino”, “idade” : 30, “skills” : [ “Java”, “MongoDB”]}
> db.pessoas.find ({ “skills” : “MongoDB” })
Queries em arrays
$elemMatch
{ _id: 1, resultados: [ 82, 85, 88 ] }{ _id: 2, resultados: [ 75, 88, 89 ] }
> db.resultados.find ({ results : { $elemMatch: { $gte: 80, $lt: 85 } } }){ "_id" : 1, "results" : [ 82, 85, 88 ] }
Operações de conjunto
$all> db.pessoas.find ( { “skills” : { $all : [“java”, “mongodb”] } )
$in> db.pessoas.find ( { “skills” : { $in : [“java”, “mongodb”] } )
Documentos aninhados
Ex: > db.usuarios.find({ “email” : {
“pessoal” : “[email protected]”, “trabalho” : “[email protected]” }})
Notação de ponto
> db.usuarios.find ({“email.trabalho” : “[email protected]”})
Documentos aninhados
Ex: { product : "Super phone",price : 100.000,reviews : [
{ user : "fred", comment : "Great!" , rating : 5 },{ user : "tom" , comment : "I agree with Fred,
somewhat!" , rating : 4 }]
}
Encontrar produtos que custem mais de 10.000 e possuem rating 5 ou mais.
> db.catalogo.find ({“pricing” : { $gte : 10.000 },“reviews.rating” : { $gte : 5 }
})
Objeto Cursor
> cur = db.catalogo.find({“pricing” : { $gte : 10.000},“reviews.rating” : { $gte : 5}
})
Ex:cur.hasNext();cur.next();cur.sort({“princing” : 1});
Contando documentos
count( )Estrutura similar ao find( ).
Ex: > db.catalogo.count({
“pricing” : { $gte : 10.000},“reviews.rating” : { $gte : 5}
})
Atualizando documentos
Se eu quisesse adicionar um endereço no meu cadastro?> db.pessoas.update(
{“nome” : ”Leonardo Quirino”},{“nome” : “Leonardo Loures Quirino”, “Endereço” :
“Jacarepaguá”})
Problema?
O documento passado como segundo argumento substitui o documento original como um todo!
Atualizando documentos
Operadores de atualização$set
> db.pessoas.update({“nome” : ”Leonardo Quirino”},
{$set : { “Endereço” : “Jacarepaguá”}})
$inc> db.pessoas.update({“nome” : ”Leonardo Quirino”},
{$inc : { “Idade” : 1 }})
$mul, $rename, $min, $max….
Atualizando documentos
Operadores de arrays$push & $addToSet
db.arrays.update( {“_id” : 10} , { $push : { “a” : 0 } } )db.arrays.update( {“_id” : 10} , { $push : { “a” : { $each : [ 0 ,
1 , 5 ] } } } )
$popdb.arrays.update( {“_id” : 10} , { $pop : { “a” : 1 } } )
$pulldb.arrays.update( {“_id” : 10} , { $pull : { “a” : 50 } } )
$pullAlldb.arrays.update( {“_id” : 10} , { $pullAll : { “a” : [ 0 , 5 ] } } )
Atualizando documentos
Upsert> db.teste.update ( { username : 'fulano' }, { '$set' : { 'interests': [ “FIFA” , “Ps4” ] } } , { upsert : true } );
Multi Update> db.empregados.update(
{ }, { '$set' : { “grupo”: “Totvs” } } , { multi : true } );
Removendo documentos
remove( )Estrutura similar ao find( ).
Ex: > db.catalogo.remove( {
“pricing” : { $gte : 10.000},} )
> db.pessoas.remove( { } );> db.pessoas.drop( { } );
Performance
Modelagem de schemas
Índices
Bancos relacionaisBasicamente focar na 3FN
MongoDBQual schema que os documentos devem seguir ?Quais dados serão mais lidos x dados mais escritos?E mais importante, como atender a sua aplicação de forma
específica?
Se você trabalhar com sua base do mesmo jeito que faria com um banco relacional, você muito provavelmente não vai estar fazendo da melhor forma.
Schemas flexíveis
Modelando schemas
Frequência de acesso dos dados? Leitura de Documentos aninhados é muito rápida
Garantir consistência na relação entre documentos?Aproveitar operações atômicas
Qual estrutura tende a crescer/ser modificada?Evitar explosão de dados em arrays
Tamanho máximo de um documento = 16 MB
Uma estrutura de dados ordenada que armazena referências aos dados do banco.Aumenta muito a performance da leituraPode diminuir a performance de escritaOcupa espaço no armazenamentoÍndice obrigatório em _id
Índices
Índices
Tipos de Índices
Índice simples ( individual ou composto )Arrays (índice multikey)Índice únicoÍndice esparsoÍndice TTL (Time To Live)Índice Geoespacial (2D ou esférico)Índice de texto
Como escolher um índice?
Entenda as necessidades da aplicaçãoQuais queries demoram a executar?Quais dados são frequentemente usados?Experimentação!
Como escolher um índice?
Comando explain( )> db.productos.explain().find( { categoria: "games" } )
Retorna dados sobre o planejamento interno e a execução das queriesPasso a passo da buscaBusca por índice ou busca diretaNúmero de índices e documentos lidos e retornados
Réplicas
Redundância de dados em nós de servidores MongoDB
Alta disponibilidade
Redundância de dados
Recuperação de desastres
Conjunto de réplicas
Composto de 1 nó primário e N secundários.
Trabalha com replicação de declaraçõesAssíncrona ( padrão )Síncrona
Contexto com recuperação e configuração automática, comunicação com aplicação de forma transparente.
Permite flexibilidade de acesso com leitura em servidores secundários.
Sharding
Processo de armazenar um conjunto massivo de dados através de um cluster de servidores MongoDB.
Objetivo de evitar que um número grande de requisições de leitura e escrita exaustem os recursos de um servidor.
Sharding
Pode ser, e é recomendado que seja, utilizado em conjunto com conjuntos de Réplicas.A aplicação se comunica de forma transparente com um processo MongoS que distribui as requisições atráves dos shards
Particionamento de dados
Os dados em um shard são particionados em nível de coleção. As coleções selecionadas são particionadas a partir de Shard Keys.A shard key é um dos índices, ou faz parte de um índice composto da coleção, mas cada coleção só pode ter 1 shard key.
Shard keys
A Chave errada pode fazer com que o cluster perca o propósito.
Escolher uma chave com presença praticamente obrigatória.
Evitar chaves que cresçam monotonicamente
Range based ( padrão )
Hash based
Shard keys
Framework de agregação
Operações que processam os dados e retornam resultados computados.
Origem na cláusula Group BY do SQL.
Comandos singularesPipeline de agregaçãoMap Reduce
Comandos singulares
count, distinct e groupEx:
{ a: 1, b: 0 }{ a: 1, b: 1 }{ a: 1, b: 4 }{ a: 2, b: 2 }
> db.colecao.count()4> db.colecao.count( { “a” : 1 } )
3> db.colecao.distinct( “a” )[1 , 2]
Pipeline de agregação
Passos dinâmicos que são executados sequencialmente pelo banco.
Consiste de um array de estágios com as operações desejados.
Grande conjunto de operações à disposição.
Operações e operadores
Operações$match$project $limit$skip$group$sort$unwind
Operações e operadores
OperadoresBooleanos
$and, $or, $notComparação
$eq, $gt, $gte, $lt, $lte, $ne e $cmpConjuntos $setEquals, $setIntersection, $setUnion, $setDifference, $setIsSubset, $anyElementTrue, $allElementsTrue Array
$size
Há também operadores aritméticos, de string, datas, de busca de texto, geoespaciais entre outros
Otimização do pipeline de agregação
O pipeline de agregação tem uma fase interna de otimização que pode transformar a forma ou a ordem das operações a serem executadas.
Ex:Um Sort seguido de Match é executado como um Match seguido de
Sort, pois assim é limitado o num de docs a ser ordenado.2 matches seguidos se tornam 1 matchSkip e limit viram limit e skip.
{ $skip: 10 } , { $limit: 5 } -> { $limit: 15 } , { $skip: 10 }Sort seguido de limit vira uma única fase com um sort limitado
Entre outros…
Otimização do pipeline de agregação
Também temos que otimizar nossas queriesExecutar matches e projects antes de outras operaçõesCuidado ao utilizar Unwind evitando executar seguidamente
Pipeline de agregação tem seus limites
Limites do pipeline de agregação
Entre cada fase da agregação só podem trafegar 100 MB de dadosResultado é um documento, ou seja, possui limite de 16MBAlgumas operações não são otimizadas para shards
Exemplo
Map Reduce
Framework anterior ao Pipeline de agregaçãoPassos fixos, mas com funções Javascript.
Usar somente se a flexibilidade for necessária, não é mais recomendado.
Exemplo
Frameworks Java
Java Driver
Spring Data
Morphia
Jongo
Hibernate
Cursos com certificados de conclusão.Recomendado para quem quiser tentar uma certificação.
Quer saber mais?
https://university.mongodb.com/ https://docs.mongodb.org/manual/
Perguntas?
Obrigado!
Top Related