Upload
brunno-gomes
View
2.706
Download
1
Embed Size (px)
DESCRIPTION
Slides do mini-curso de MongoDB realizado no Workshop de Software Livre 2010 do CInLUG, no Centro de Informática da Universidade Federal de Pernambuco em 24/08/2010. Instrutores: Brunno Gomes (@brunnogomes) e Daker Fernandes (@dakerfp).
Citation preview
http://cinlug-br.org/
De acordo com o mongoDB.org:
“Banco de dados escalável, de alta-performance, open-source, schema-free,
orientado-a-documentos.”
documentos
{nome: 'mongo', tipo: 'BD'}
JSON ?
JSON !
hash
dicionário
array
schema-free ?
tipagem dinâmicamigrations de graçaainda posso usar índices
migrations ?
{nome: 'mongo', tipo: 'BD'}
apenas faça:
{nome: 'mongo', tipo: 'BD', versao: 1.6}
coisas que podem fazer falta
As propriedades ACID ficam na mão do programador
Relembrando ACIDSão 4 propriedades que os BDs tradicionais fornecem às aplicações:
AtomicityGarante que um conjunto de modificações seja realizado por completo ou nada é feito
ConsistencyGarante que o banco não está em um estado inconsistente
Isolation Dados que estão durante operação são inacessíveis
DurabilityGarantia de qua transação só é finalizada quando está salva no disco
usando o mongoDB
a partir do Terminal
instalando:
> http://www.mongodb.org/downloads
> escolha a versão adequada ao seu SO e arquitetura (32-bits / 64-bits) (32
> descompacte (dezipe, desenrare) > só isso mesmo...
WARNINGAs versões de 32-bits do mongoDB são limitadas a uns 2.5 GB de dados
Oxe, porque?Como o foco dele é em performance, ele usa um sistema de mapeamento de arquivos em memória em alguns momentos, logo...
usando:
> bin/mongod <- servidor
> bin/mongo <- cliente
usando:
o cliente (vulgo shell) é baseado em Javascript
então podemos fazer qualquer coisa (que faríamos com Javascript num terminal, claro)
usando:> n1 = 5;
> n2 = 8; > if (n2 > n1) { menor = n1; } else { menor = n2; }
usando:criando um documento
> estudante = {nome: 'brunno', nota: 6};
usando:
salvando na coleção
> db.estudantes.insert(estudante);
o insert() acabou de guardar o documento estudante na coleção de estudantes,
localizada na base teste
a coleção estudantes não precisou ser previamente criada, a partir do momento que é
usada o mongoDB cria uma coleção
a base teste é usada por padrão quando conectamos ao mongoDB, podemos escolher outras bases e coleções quando quisermos
usando:escolhendo base e coleção
> show dbs;
> use nomedabase; > show collections; > db.nomedacolecao.metodo();
usando:podemos usar atalhos
> est = db.estudantes;
> est.insert({nome: 'daker', nota: 10});
o campo _id:
todo documento inserido no banco deve conter um campo _id com valor único em toda
coleção, caso ele não exista é automaticamente adicionado (nesse caso usando o tipo binário ObjectId, que servirá
como índice padrão).
usando:
resgatando documentos
> db.estudantes.find();
o find() faz uma consulta e retorna todos os documentos que correspondem ao filtro
passado ao find()
nesse caso o método find() não recebeu nenhum parâmetro, então ele retornou todos
os documentos daquela coleção
usando:resgatando documentos
> est.find({nota: 7}); > est.find({nota: { '$gt': 7});
o $gt é um dos operadores especiais, nesse caso significa '>' (maior que/greater than)
existem vários outros:
$lt - '<', $lte - '<=', $gte - '>=', $ne - '!=' $in - 'no array', $nin - '! no array'
usando:
o findOne()
> est.findOne({nota: 7});
o findOne() retorna o primeiro documento encontrado que corresponda aos parâmetros
da consulta
quando você estiver utilizando o driver da sua linguagem ele já retorna um objeto do tipo
dicionário/hash/coisaDaSuaLinguagem
usando:atualizando um documento
> est.update({ name: 'brunno'}, { name: 'brunno, nota: 10 });
o update() recebe como primeiro parâmetro os filtros da consulta e como segundo a
atualização a ser feita. nesse caso foi passado um outro documento, então ele vai
sobrescrever tudo
existem outras maneiras de se atualizar documentos
usando:atualizando um documento
> est.update({ name: 'brunno' }, { $set: { nota: 8 } });
o $set define o valor 8 no campo nota
caso 'nota' não exista, é criado com valor 8
usando:atualizando um documento
> est.update({ name: 'brunno' }, { $push: { cadeira: 'p1' } });
o $push adiciona o valor 'p1' ao campo 'cadeiras', se 'cadeiras' é um array/lista.
caso 'cadeiras' não exista, é criado com a lista ['p1'] como valor
usando:removendo documentos
> est.remove(); > est.remove({ name: 'brunno' });
o remove() remove (é mêmo?) os documentos que correspondam aos parâmetros de
consulta passados no método
caso seja chamado sem parâmetros, remove todos os elementos de uma coleção
ok, já sei o básico, mas como aproveitar mais o que o
mongoDB oferece?
Agregue seus dados de acordo com o uso
Princípio da Localidade Espacial
Também Binha!
Princípio da Localidade Espacial
Utilizar espaço contíguo no disco para evitar reposicionamento da agulha no disco que é uma operação de alta latência.Caso a agulha seja movida, quanto menor o deslocamento, mais rápido será a operação.
História: Quero mostrar meus posts, os seus comentários com as informações de cada usuário.
Estudo de Caso
Modelo Relacional
post = {'_id': 1, 'titulo': "lambda lambda lambda", 'texto': “Live Long and Prosper!”, 'autor_id': 34}
autor1 = {'_id': 34, 'nome': 'Spock'}
autor2 = {'_id': 33, 'nome': 'Kirk'}
comentario = {'post_id': 1, 'autor_id': 33, 'texto': 'Excelente Spock'}
Como ocorre o acesso ao disco?
Como ocorre o acesso ao disco?
Modelo Não Normalizadopost = {'_id': 1, 'titulo': 'lambda lambda lambda', 'texto': 'era uma vez...', 'autor': {'_id': 1, 'nome': 'spock'}, 'comentarios': [ {'autor': 'kirk', 'texto': 'muito bom!'}]}
E como ocorre o acesso ao disco agora?
Join tables é muito custoso!
$$$
WARNING Dados não normalizados implica na duplicação de dados.
Se os dados da duplicação forem críticos, devem ser atualizado nas múltiplas ocorrências.
WARNING Otimize quando possível.
Quando a duplicação for difícil de ser tratada, normalize seus dados
muito + coisas legais
ÍndicesCriam um atalho para a busca de dados Acesso rápido aos ítens indexados
Índices
db.posts.ensureIndex({'hora': 1});
db.posts.ensureIndex({'autor':1});
Índices fazem o que?
Quando eu devo usar Índices?
Otimizar consultas por um campo específicoOtimizar buscas ordenadasOtimizar buscas dentro de intervalos de valores
Chaves Embarcadas e múltiplas
db.posts.ensureIndex({'comentarios.autor': 1});
Chaves Compostas:
db.factories.insert({ 'name': "General Motors", 'metro': { 'city': "New York", 'state': "NY" } } );db.factories.ensureIndex( { metro : 1 } );
WARNINGNão crie índices sem necessidade, ou para consultas rarasÍndices aumentam o tempo de inserção de documentosAtualização nos documentos com índices demoram +
WARNINGÍndices podem ocupar muita memória Ao criar um índice em uma coleção não vazia, essa operação (por padrão) congelará o processo do mongoDB até concluir a indexação. Utilize:
db.things.ensureIndex( {'x':1},{'background':true});
tem +
Chaves decrescentes Chaves únicas Chaves dropáveis dropIndex reIndex Índices Geoespaciais...
Capped Collections O que são? São coleções sem índices, sem _id e com tamanhos fixos.
db.createCollection('visitas', {'capped':true,'size':100000})
Capped Collections Operações idênticas a uma coleção comum: db.visits.insert({ 'ip':'108.23.47.98', 'timestamp': 1292177707})
db.visits.remove()
Capped CollectionsPara que servem?
Inserção de dados otimizada Rápido para consultas do tipo: as últimasConsultas genéricas são lentasMapReduce mais rápido (mais adiante)
Ex.: Logs, Coleta massiva de dados
Existem N maneiras de fazer uma consulta, Certo?
Mas qual é a mais eficiente? Na dúvida utilize Profiling: db.posts.find().explain()
Profiling
{ 'cursor' : "BasicCursor", --> Tipo de Cursor da consulta 'nscanned' : 1, --> Índices visitados 'nscannedObjects' : 1, --> Objetos visitados 'n' : 14, --> Quantidade de objetos retornados 'millis' : 1, --> Tempo de execução da consulta "indexBounds" : {} --> Range dos índices que foram varridos }
Profiling
É uma Coleção de ArquivosDocumentos > 4MB Armazenar dados binários
ex.: Vídeos, Mapas, ...Esquema chave/valorDisponível através do driver de alguma linguagem.
GridFS
Sharding & Replica
Escalabilidade horizontalFácil adição de shards Sem pontos únicos de rupturaBalanceamento de carga automáticoProcessamento distribuído (MapReduce)
Sharding & Replica
É um modelo de programação criado pelo Google para processar quantidades
massivas de dados,na escala de Terabytes.
Esse modelo permite um escalabilidade horizontal em um cluster de
computadores.
MapReduce
Paper: http://labs.google.com/papers/mapreduce.html
ProblemasConsulta em bases gigantesRecuperação de informaçãoEngenhos de Busca (Yahoo!)Mineração de DadosAnálise de LogsIndicação de Amigos
MapReduce
E como funciona?
MapReduce
1 - Map: Para cada item da entrada executa uma função e retorna um par
<Chave1, Valor1> intermediário.
2 - Reduce: Junte os pares <Chave1,Valor1> com chaves iguais emitidas pela função
anterior, processe e retorne um par <Chave2,Valor2> como resultado final.
MapReduce
1 - Χάρτης: Για κάθε σημείο της εισόδου εκτελεί μια λειτουργία και επιστρέφει ένα ζεύγος
<Βασικά1, αξία1> μεσάζοντα.
2 - Μείωση: Συμμετοχή στο <Βασικά1,αξία1> ζευγάρια με ίσα κλειδιά που εκδίδονται από την
προηγούμενη λειτουργία, διαδικασία και να επιστρέψει ένα <Βασικά2,αξία2> ζεύγος ως το
τελικό αποτέλεσμα.
MapReduce
Na Prática:
map = function() { var words = this.conteudo.split(' '); for(var i = 0; i < words.length; i++) { emit(words[i], {'count': 1,'posts':[this._id]}); }}
MapReduce
reduce = function(word, tags) { var total = 0; var posts = []; for(var i = 0; i < tags.length; i++) { total += tags[i]['count']; posts = posts.concat( tags[i]['posts']); } return {'count': total, 'posts': posts}; }
MapReduce
GO!
db.posts.mapReduce(map,reduce);
MapReduce
Por padrão, o mongodb cria uma coleção temporária: show collections tmp.mr.mapreduce_1282610145_3 Utilizando os drivers da sua linguagem, é possível renomear essa coleção temporária.
MapReduce
...OUCriamos uma função de finalização:
finalize = function(word, tags) { db.tagCloud.insert( {'keyword':word, 'count': tags['count'], 'posts': tags['posts']})}
MapReduce
db.posts.mapReduce(map,reduce, {'finalize':finalize});
MapReduce
mais ?
drivers para:
CC++JavaJavascriptPHPPerlPythonRubyREST C# e .NetClosure ColdFusionDelphiErlang
FactorFantomF#GoGroovyHaskellLuanode.jsObjective CPowershell ScalaSchemeSmalltalk...
mais informações?
http://www.mongodb.org/display/DOCS
http://www.mongodb.org/display/DOCS/Drivers