Mongodb workshop cinlug

Post on 29-Jun-2015

1.022 views 0 download

Transcript of Mongodb workshop cinlug

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

Brunno Gomes

twitter.com/brunnogomes brunnolgp@gmail.com

Daker codecereal.blogspot.com twitter.com/dakerfp

dfp@cin.ufpe.br

daker.pinheiro@openbossa.org