Diferència entre revisions de la pàgina «MongoDB»
Línia 137: | Línia 137: | ||
== Indexes == | == Indexes == | ||
Els indexes augmenten la velocitat de les consultes. Si no fos per ells, cada cop que fem una recerca (find) hauriem de repassar tota la BBDD, i si aquesta té una xifra elevada de registres (diguem-ne, 10 milions) la consulta serà lenta, i farà que el sistema sigui impracticable. | Els indexes augmenten la velocitat de les consultes. Si no fos per ells, cada cop que fem una recerca (find) hauriem de repassar tota la BBDD, i si aquesta té una xifra elevada de registres (diguem-ne, 10 milions) la consulta serà lenta, i farà que el sistema sigui impracticable. | ||
+ | |||
+ | Referència: http://docs.mongodb.org/manual/indexes/ | ||
Vídeos de MongoDB University: | Vídeos de MongoDB University: | ||
Línia 151: | Línia 153: | ||
Per crear un índex (1 és ascendent i -1 descendent): | Per crear un índex (1 és ascendent i -1 descendent): | ||
− | > db.<colleccio>.ensureIndex({<camp1>:1,<camp2>:-1,...}} | + | > db.<colleccio>.'''ensureIndex'''( {<camp1>:1,<camp2>:-1,...} , <opcions> } |
+ | Per destruïr-lo: | ||
+ | > db.<colleccio>.'''dropIndex'''({<camp1>:1,<camp2>:-1,...}} | ||
Per saber els índexes de tot el sistema: | Per saber els índexes de tot el sistema: | ||
> db.system.indexes.find() | > db.system.indexes.find() | ||
Per saber els índexes que té una col·lecció: | Per saber els índexes que té una col·lecció: | ||
− | > db.<colleccio>.getIndexes() | + | > db.<colleccio>.'''getIndexes'''() |
+ | Espai ocupat pels índex (ens importa per saber si es poden tenir a la RAM: performance): | ||
+ | > db.<colleccio>.getIndexSize() | ||
+ | Profiling (dades sobre el temps i indexes emprats per la consulta): | ||
+ | > db.<colleccio>.find(...).'''explain()''' | ||
+ | (temps = "millis") | ||
+ | |||
+ | |||
+ | === Opcions === | ||
+ | Camp únic (unique): | ||
+ | > db.<colleccio>.ensureIndex( {<camp>:1} , {'''unique''':true} } | ||
+ | dropDups: Si la col·lecció té duplicats al crear índex amb camp únic ens els carreguem: (no molt recomanat) | ||
+ | > db.<colleccio>.ensureIndex( {<camp>:1} , {unique:true, dropDups:true} } | ||
+ | '''Sparse indexes''': podem indexar camps que no els tenen tots els documents (en principi seríen "null") => aquests documents no s'indexaran | ||
+ | > db.<colleccio>.ensureIndex( {<camp>:1} , {unique:true, '''sparse:true'''} } | ||
+ | OJU, perquè els SPARSE indexes poden donar lloc a comportaments diferents en les consultes depenent si hem creat l'índex o no. Per exemple: | ||
+ | > db.<colleccio>.find().sort( {"size":1} ) | ||
+ | ...els documents sense el camp ''size'' apareixeran si NO hem creat el ''sparse index''. Si el creem, no apareixeran. | ||
Línia 173: | Línia 194: | ||
> ensureIndex( {adreces.telefons:1} ) | > ensureIndex( {adreces.telefons:1} ) | ||
(array d'adreces amb un camp telèfons incrustat) | (array d'adreces amb un camp telèfons incrustat) | ||
+ | |||
<br> | <br> |
Revisió del 22:15, 17 des 2013
Contingut
Intro No-SQL
Algunes característiques:
- Treballem amb documents.
- La inconsistència de dades deixa de ser una prioritat.
- Treballem amb incrustació (embedding). Exemple de blog: posts+comments
- Dades relatives al document incrustades en el mateix (exemple de blog amb post+comment). Això ajuda a mantenir certa consistència.
- Millora la velocitat d'accés (performance). Latència dels discs alta (1ms) però ample de banda alt (BW).
- No té FKs. En canvi té operacions atòmiques.
- No té transaccions (consistència temporal). Alternatives:
- Reestructurar la nosta BBDD per treballar en un sol tipus de document (schema).
- Implementar-la en el nostre software.
- Tolerar certa inconsistència temporal (dependrà del tipus d'aplicació).
- Relacions:
- 1:1 millor sempre unir-les en un sol doc a no ser que excedeixi 16 MB (maxim).
- 1:N si "N" son molts millor apuntar dels molts al 1 (amb el _id). També es pot fer al revés amb una llista.
- Hi ha una variant típica de 1:pocs que és el cas que ens agrada per incrustar.
- N:N (molts:molts) calen llistes (es poden posar a les 2 col·leccions tot i que això significa que la app ha de controlar la consistència
- Sempre intentem incrustar docs.
Info:
- Schemaless and document based
- No joins, no SQL
- RDBS is not scalability in general machines
- memcache is not highly functional but scales well
- Joins don't scale well
- Documents have a 16 MB limit on 32 bit OS's
- Transactions are unavailable
- Crud Operations exists as wire protocols
- 'id' is immutable, and made up of Current Time, Machine Id, Process ID and global Counter
- remove is not an isolated transaction.
Primeres passes
- Instal·lar darrera versió (2.4.8) a Ubuntu:
- Monogo shell:
$ mongo
- Seleccionar una db (o crear):
> use <nom_db>
- Exemple amb dades:
- Importar-lo:
$ mongoimport -d students -c grades < grades.ef42a2b3e7ff.js
- ...
JavaScript en la Mongo Shell
Això ens facilita molt la creació i manipulació de les dades. Per exemple, per crear un munt de documents que continguin un "num" i una "cosa" a triar aleatòriament entre "tablet", "smartphone" i "xocolata":
for (i=0;i<100000;i++) {
db.coses.save( {
"num":i,
"cosa": ["tablet","smartphone","xocolata"][Math.floor(Math.random()*3)]
})
}
Un altre exemple:
for (i=0;i<1000;i++) {
names=["examen","treball","questionari"];
for(j=0;j<3;j++) {
db.notes.insert({
"estudiant":i,
"tipus": names[j],
nota : Math.round(Math.random()*100)
});
}
}
CRUD
Create Read Update Delete
- En Mongo Shell: http://docs.mongodb.org/manual/reference/crud/
- En PyMongo: http://api.mongodb.org/python/current/api/pymongo/collection.html
Create / Insert / Save
Per crear documents dins d'una col·lecció:
> db.<coleccio>.save( <JSON_obj> )
Read / Select / Find
La operació de query més estàndard en MongoDB és FIND. Alguns exemples:
> db.<coleccio>.findOne() > db.<coleccio>.findOne( {"tipus":"examen"} ) > db.<coleccio>.find() > db.<coleccio>.find( {estudiant:103} )
OJU: en Pymongo és find_one enlloc de findOne
Si ho volem veure una mica més ben formatat:
> db.<col>.find().pretty()
El 2n argument és per seleccionar camps (i excloure):
> db.<col>.find( {"tipus":"examen",nota:50}, {"estudiant":true,"_id":false} )
Operadors: estudiants amb examens amb notes > 90
> db.<col>.find( {"tipus":"examen", nota: {$gt:90} }, {"estudiant":true,"_id":false} )
Estudiants amb notes entre 65 i 71: db.grades.find( {"type":"exam",score: {$gte:65,$lte:71}} ).sort({"score":1})
Altres operadors: http://docs.mongodb.org/manual/reference/operator/query/
TODO: Unir dues queries amb $or...
Ordenar resultats (sort): http://docs.mongodb.org/manual/reference/method/cursor.sort/
Update
Referències:
- Mongo Shell Update: http://docs.mongodb.org/manual/tutorial/modify-documents/
- Pymongo Update: http://api.mongodb.org/python/current/api/pymongo/collection.html#pymongo.collection.Collection.update
- Update operators: http://docs.mongodb.org/manual/reference/operator/update/
La operació de Update es pot resoldre de 2 maneres:
- db.<col>.update( ... ) ...amb els següents operadors http://docs.mongodb.org/manual/reference/operator/update/#id1
- Exemple en mongo shell:
self.posts.update( {"_id":33}, {$addToSet:{"comments":comment}} )
- Exemple en pymongo:
self.posts.update( {"_id":33}, {"$addToSet":{"comments":comment}} )
- Exemple en mongo shell:
- db.<col>.save( <doc> ) ...on <doc> ha de ser el nou document modificat amb el "_id" (PK) pertinent
Delete / Remove
Referències:
- Pymongo remove: http://api.mongodb.org/python/current/api/pymongo/collection.html#pymongo.collection.Collection.remove
- ...
Indexes
Els indexes augmenten la velocitat de les consultes. Si no fos per ells, cada cop que fem una recerca (find) hauriem de repassar tota la BBDD, i si aquesta té una xifra elevada de registres (diguem-ne, 10 milions) la consulta serà lenta, i farà que el sistema sigui impracticable.
Referència: http://docs.mongodb.org/manual/indexes/
Vídeos de MongoDB University:
- Introducció als índexes (segueix la sèrie de vídeos, hi ha diversos d'una durada de pocs minuts cadascun).
- Un índex accelera les cerques
- El mateniment de l'índex alenteix les insercions.
- Índexes i performance (velocitat d'accés).
- findOne() és més ràpid perquè quan troba una mostra ja surt.
- si el ID que busquem és baix va ràpid (al principi de la col·lecció).
- Si el ID que busquem és alt triga més.
- find() triga igual perquè ha de buscar en tota la base de dades: lent (sense índex)
- Buscar un element que no existeix: triga molta estona.
- ...
Per crear un índex (1 és ascendent i -1 descendent):
> db.<colleccio>.ensureIndex( {<camp1>:1,<camp2>:-1,...} , <opcions> }
Per destruïr-lo:
> db.<colleccio>.dropIndex({<camp1>:1,<camp2>:-1,...}}
Per saber els índexes de tot el sistema:
> db.system.indexes.find()
Per saber els índexes que té una col·lecció:
> db.<colleccio>.getIndexes()
Espai ocupat pels índex (ens importa per saber si es poden tenir a la RAM: performance):
> db.<colleccio>.getIndexSize()
Profiling (dades sobre el temps i indexes emprats per la consulta):
> db.<colleccio>.find(...).explain()
(temps = "millis")
Opcions
Camp únic (unique):
> db.<colleccio>.ensureIndex( {<camp>:1} , {unique:true} }
dropDups: Si la col·lecció té duplicats al crear índex amb camp únic ens els carreguem: (no molt recomanat)
> db.<colleccio>.ensureIndex( {<camp>:1} , {unique:true, dropDups:true} }
Sparse indexes: podem indexar camps que no els tenen tots els documents (en principi seríen "null") => aquests documents no s'indexaran
> db.<colleccio>.ensureIndex( {<camp>:1} , {unique:true, sparse:true} }
OJU, perquè els SPARSE indexes poden donar lloc a comportaments diferents en les consultes depenent si hem creat l'índex o no. Per exemple:
> db.<colleccio>.find().sort( {"size":1} )
...els documents sense el camp size apareixeran si NO hem creat el sparse index. Si el creem, no apareixeran.
Multi-indexes
Indexes sobre arrays, per ex:
{ tags: ["btt","tennis","futbol"],
categories: ["esports","hobbies"] }
Es poden crear índexes sobre un array, però no sobre 2 alhora:
> ensureIndex( {tags:1} ) OK > ensureIndex( {categories:-1} ) OK >ensureIndex( {tags:1, categories:-1} )NO ES POT
Posar un índex en un camp intern d'un document, per ex, en una col·lecció d'usuaris:
> ensureIndex( {adreces.telefons:1} )
(array d'adreces amb un camp telèfons incrustat)
Exercicis
...