mongodb : la base nosql qui réinvente la gestion de données
DESCRIPTION
MongoDB : la base NoSQL qui réinvente la gestion de donnéesTRANSCRIPT
@dwursteisen
MongoDB
11/28/13 !1
la base NoSQL qui réinvente la gestion de données
MongoDBBig Database
@DWURSTEISEN
http://fr.slideshare.net/soatexpert
WARNING
Il n’y a pas si longtemps que cela, un site internet faisait sensation…
20:00:00
Ce site déboite
Oups ! Database Error
no more space disk available
BIG DATA
Animation Soat
Devoxx France 2013
Caractéristiques(sous le capot)
Orienté document
{! "_id": "e
nigme1", !
"titre": "Enigme du ve
ndredi", !
"activation": true!
}
{! "_id": "e
nigme1", !
"titre": "Enigme du ve
ndredi", !
"activation": true!
}
{! "_id": "enigme1", ! "activation": true, ! "joueurs": [! { "email": "[email protected]", "score": 20 }! ], ! "indices": [! {! "contenu": "je suis ton père",! "flashcode": "111-111-1111", ! "joueurs": [ { "email": "[email protected]" } ]! } ]!}!
Sans schéma
CREATE TABLE example_default_now ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, data VARCHAR(100), created TIMESTAMP DEFAULT NOW() );
CREATE TABLE example_default_now ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, data VARCHAR(100), created TIMESTAMP DEFAULT NOW() );
Sans transaction
Transaction
Transaction
Transaction
Transaction
Transaction
Transaction
Sans transaction
Sans transaction
Sans transaction
Sans transaction
Update atomique
Sans jointure
{! "_id": "enigme1", ! "activation": true, ! "joueurs": [! { "email": "[email protected]", "score": 20 }! ], ! "indices": [! {! "contenu": "je suis ton père",! "flashcode": "111-111-1111", ! "joueurs": [ { "email": "[email protected]" } ]! } ]!}!
{! "_id": "enigme1", ! "activation": true, ! "joueurs": [! { "email": "[email protected]", "score": 20 }! ], ! "indices": [! {! "contenu": "je suis ton père",! "flashcode": "111-111-1111", ! "joueurs": [ { "email": "[email protected]" } ]! } ]!}!
jointure ?
Distribué
Document = 16Mb Hard Limit
Design des structures
des données
Type Exemple
Int / Double / … { a: 1 }
Boolean { b: true }
String { c: ‘hello’ }
Array { d: [1, 2, 3] }
Date {e: ISODate("2012-12-19T06:01:17.171Z")
ObjectId {f: ObjectId(‘123456’)}
Object {g: {a: 1, b: true}}
…
http://docs.mongodb.org/manual/reference/bson-types/
Organiserles données selon leurs
Utilisations
ci gît la 4ème forme
normale
Structure de donnée pour l’affichage d’un message ?
Question :
2
2
Auteur
2
Auteur Contenu
2
Auteur Contenu
Recouicoui
{ _id: ObjectId(11),
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. »,
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla »,
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla », …
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla », … recouicoui: [ObjectId(22), ObjectId(33)]
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla », … !
recouicoui: 2, // compteur
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla », … !
recouicoui: [{user: {…}, {user: {…}]
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla », … !
recouicoui: [{user: {…}, {user: {…}]
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla », … !
recouicoui: [{user: {…} * 789013]
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla », … !
recouicoui: [{user: {…} * 789013]
> 16Mb
2
2
Information partielle
{ _id: ObjectId(11), user: {mail: « user1 », avatar: « http://…. », content: « blabla », … recouicoui: { users: [{user: {…} * 5], compteur: 789013 }
bonnecomplexe
structure de donnée est
Le design d’une
Parlez-vous
Français ?
Query languageselect * from table
Le shell : mongo
Lecture
Sélection d’un document
db.collection.findOne(…)
Sélection d’un document
db.collection.findOne(…)
Query
Sélection de documents
db.collection.find(…)
Sélection et mise à jour de document
db.collection.findAndModify(…)
Champ unique {_id: ‘azerty’}
Champ unique {_id: ‘azerty’}
{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! "activation": true!}
✓
Champ unique {_id: ‘azerty’}
{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! "activation": true!}
✓{! "_id": "azerty", ! "activation": true,! "titre": "Enigme du vendredi"!}
✓
{! "_id": "azerty12345", ! "activation": true,! "titre": "Enigme du vendredi"!}
✗
Champ unique {_id: ‘azerty’}
{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! "activation": true!}
✓{! "_id": "azerty", ! "activation": true,! "titre": "Enigme du vendredi"!}
✓
Sous document spécifique {auteur: {nom: ‘Wursteisen’}}
Sous document spécifique {auteur: {nom: ‘Wursteisen’}}
{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen"}!} ✓
Sous document spécifique {auteur: {nom: ‘Wursteisen’}}
{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen"}!} ✓{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen", "prénom":"David"}!} ✗
Sous document spécifique {auteur: {prénom: ‘David’, nom: ‘Wursteisen’}}
Sous document spécifique {auteur: {prénom: ‘David’, nom: ‘Wursteisen’}}
{! "_id": "azerty", ! "auteur": {"prénom":"David", "nom":"Wursteisen"}!} ✓
Sous document spécifique {auteur: {prénom: ‘David’, nom: ‘Wursteisen’}}
{! "_id": "azerty", ! "auteur": {"prénom":"David", "nom":"Wursteisen"}!} ✓{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen", "prénom":"David"}!} ✗
Sous champ {‘auteur.nom’: ‘Wursteisen’}
Sous champ {‘auteur.nom’: ‘Wursteisen’}{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen"}!} ✓
Sous champ {‘auteur.nom’: ‘Wursteisen’}{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen"}!} ✓{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen", "prénom":"David"}!} ✓
Sous champ {‘auteur.nom’: ‘Wursteisen’}{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen"}!} ✓{! "_id": "azerty", ! "auteur": {"nom":"Wursteisen", "prénom":"David"}!} ✓{! "_id": "azerty", ! "auteur": {"nom":"Bob", "prénom":"David"}!} ✗
Champ unique {recouicoui: {$gt: 20}}
Champ unique {recouicoui: {$gt: 20}}
{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! "recouicoui": 50!}
✓
Champ unique {recouicoui: {$gt: 20}}
{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! "recouicoui": 50!}
✓{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! "recouicoui": 10!}
✗
Champ unique {recouicoui: {$gt: 20}}
{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! "recouicoui": 50!}
✓{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! "recouicoui": 10!}
✗{! "_id": "azerty", ! "titre": "Enigme du vendredi", ! !}
✗
Écriture
Insertion d’un document
db.collection.insert(…)
Insertion d’un document
db.collection.insert(…)
Document
Update d’un document
db.collection.update(<query>, <update>)
Update d’un document
db.collection.update(<query>, <update>)
modifier
Update de documents
db.collection.update(…, …, {multi: true})
Écrire un document db.collection.update(…, {prénom:’David’})
Écrire un document db.collection.update(…, {prénom:’David’})
{! "_id": "azerty", ! "nom": "wursteisen", ! "prénom": "bob"!}
Écrire un document db.collection.update(…, {prénom:’David’})
{! "_id": "azerty", ! "nom": "wursteisen", ! "prénom": "bob"!}
{! "_id": "azerty", ! "prénom": "David"!}
Modifier un champ db.collection.update(…, {$set: {prénom:’David’}})
Modifier un champ db.collection.update(…, {$set: {prénom:’David’}})
{! "_id": "azerty", ! "nom": "wursteisen", ! "prénom": "bob"!}
Modifier un champ db.collection.update(…, {$set: {prénom:’David’}})
{! "_id": "azerty", ! "nom": "wursteisen", ! "prénom": "bob"!}
{! "_id": "azerty", ! "nom": "wursteisen", ! "prénom": "David"!}
Incrémentation db.collection.update(…, {$inc: {recouicoui: 2 }})
Incrémentation db.collection.update(…, {$inc: {recouicoui: 2 }})
{! "_id": "azerty", ! "nom": "wursteisen", ! "recouicoui": 5!}
Incrémentation db.collection.update(…, {$inc: {recouicoui: 2 }})
{! "_id": "azerty", ! "nom": "wursteisen", ! "recouicoui": 5!}
{! "_id": "azerty", ! "nom": "wursteisen", ! "recouicoui": 7!}
Ajout dans un tableau db.collection.update(…, {$push: {contact: ‘Robert’ }})
Ajout dans un tableau db.collection.update(…, {$push: {contact: ‘Robert’ }})
{! "_id": "azerty", ! "contact": ["John", "Bob"] !}
Ajout dans un tableau db.collection.update(…, {$push: {contact: ‘Robert’ }})
{! "_id": "azerty", ! "contact": ["John", "Bob"] !}
{! "_id": "azerty", ! "contact": ["John", "Bob", "Robert"] !}
Index
db.couicoui.ensureIndex({ name:1 })Index simple
db.couicoui.ensureIndex({ name:1, date:-1 })Index composé
db.couicoui.ensureIndex({ geo: ‘2d‘ })Géo index
db.couicoui.ensureIndex({ name:1 }, {expireAfterSeconds: 3600})Index avec Time To Live
db.find({…}).explain()
{ "cursor" : "<Cursor Type and Index>", "n" : <num>, "nscanned" : <num>, "scanAndOrder" : <boolean>, … }
Replica Set
Driver
Primary
Secondary Secondary
Driver
Primary
Secondary Secondary
Écriture
Driver
Primary
Secondary Secondary
Écriture
Réplication
Driver
Primary
Secondary Secondary
Écriture
Réplication Réplication
Driver
Primary
Secondary Secondary
Écriture
Réplication Réplication
Lecture
Driver
Primary
Secondary Secondary
Écriture
Réplication Réplication
Lecture
Lecture
Primary
Secondary Secondary
Primary
Secondary Secondary
Heartbeats
Primary
Secondary Secondary
Heartbeats
Primary
Secondary Secondary
Primary
Secondary Secondary
Primary ?
Primary
Primary Secondary
Primary ?
Primary
Primary Secondary
Primary ?
Réplication
Primary
Primary Secondary
Primary ?
Réplication
Primary
Primary Secondary
Primary ?
RéplicationHeartbeats
Primary
Primary Secondary
Primary ?
RéplicationHeartbeats
Secondary
Primary Secondary
Primary ?
RéplicationHeartbeats
Secondary
Primary Secondary
Primary ?
RéplicationHeartbeats
Write Concernnotification d’écriture
collection.insert(…, WriteConcern.ACKNOWLEDGED); !
db.getLastError();
(dépendant du driver)
collection.insert(…, WriteConcern.ACKNOWLEDGED); !
db.getLastError();
(dépendant du driver)
w=1
collection.insert(…, WriteConcern.ACKNOWLEDGED); !
db.getLastError();
(dépendant du driver)
w=1
bloquant
disable acknowledgmentw=0
Driver
Mongod
write
Driver
Mongod
write
Driver
Mongod
getLastErrorw=0
write
Driver
Mongod
getLastError response
getLastErrorw=0
acknowledgmentw=1
Driver
Mongod
write
Driver
Mongod
write
Driver
Mongod
getLastErrorw=1
write
Driver
Mongod
getLastErrorw=1
apply
write
Driver
Mongod
getLastError response
getLastErrorw=1
apply
write
Driver
Mongod
getLastError response
getLastErrorw=1
apply
bloquant
journalj=1
Driver
Mongod
write
Driver
Mongod
write
Driver
MongodgetLastError
w=1,j=1
write
Driver
MongodgetLastError
w=1,j=1
apply
write
Driver
MongodgetLastError
w=1,j=1
apply write to journal
write
Driver
Mongod
getLastError response
getLastErrorw=1,j=1
apply write to journal
write
Driver
Mongod
getLastError response
getLastErrorw=1,j=1
apply write to journal
bloquant
replica acknowledgmentw=2
Driver
Primary
Secondary
Secondary
write
Driver
Primary
Secondary
Secondary
write
Driver
PrimarygetLastError
w=2
Secondary
Secondary
write
Driver
PrimarygetLastError
w=2apply
Secondary
Secondary
write
Driver
PrimarygetLastError
w=2apply
Secondary
Secondary
replicate
write
Driver
PrimarygetLastError
w=2apply
Secondary
Secondary
replicate
write
Driver
Primary
getLastError response
getLastErrorw=2
apply
Secondary
Secondary
replicate
write
Driver
Primary
getLastError response
getLastErrorw=2
apply
Secondary
Secondary
replicate
bloquant
write
Driver
Primary
getLastError response
getLastErrorw=2
apply
Secondary
Secondary
replicate
replicatebloquant
Sharding
Répartition
collection
Shard2 Shard3Shard1
collection
Shard2 Shard3Shard1
collection
{x: min} {x: max}{x: -11} {x: 50}
Avec une clé de sharding
Mongos
db.collect.find({key: …})
Mongos
db.collect.find({key: …})
Mongos
db.collect.find({key: …})
Mongos
db.collect.find({key: …})
Mongos
db.collect.find({key: …})
Avec une clé non shardé
Mongos
db.collect.find({other: …})
Mongos
db.collect.find({other: …})
Mongos
db.collect.find({other: …})
Clé de sharding pour gérer les messages d’un utilisateur ?
Question :
Cardinalité Répartition en écriture Isolation Fiabilité
_id
ObjectId(« 507f1f77bcf86cd799439011 »)
http://www.mongodb.com/presentations/advanced-sharding-features-mongodb-24
ObjectId(« 507f1f77bcf86cd799439011 »)
http://www.mongodb.com/presentations/advanced-sharding-features-mongodb-24
Timestamp
ObjectId(« 507f1f77bcf86cd799439011 »)
http://www.mongodb.com/presentations/advanced-sharding-features-mongodb-24
Timestamp
Host
ObjectId(« 507f1f77bcf86cd799439011 »)
http://www.mongodb.com/presentations/advanced-sharding-features-mongodb-24
Timestamp
Host
PID
ObjectId(« 507f1f77bcf86cd799439011 »)
http://www.mongodb.com/presentations/advanced-sharding-features-mongodb-24
Timestamp
Host Compteur
PID
ObjectId(« 507f1f77bcf86cd799439011 »)
http://www.mongodb.com/presentations/advanced-sharding-features-mongodb-24
Timestamp
Cardinalité Répartition en écriture Isolation Fiabilité
_id ✓ ✗ ✗ ✗
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.find({…})
Mongos
db.collect.find({…})
Mongos
db.collect.find({…})
Cardinalité Répartition en écriture Isolation Fiabilité
_id ✓ ✗ ✗ ✗hash(_id) ✓ ✓ ✗ ✗
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.find({…})
Mongos
db.collect.find({…})
Mongos
db.collect.find({…})
Cardinalité Répartition en écriture Isolation Fiabilité
_id ✓ ✗ ✗ ✗hash(_id) ✓ ✓ ✗ ✗
user ✗ ✓ ✓ ✓
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.find({…})
Mongos
db.collect.find({…})
Mongos
db.collect.find({…})
Cardinalité Répartition en écriture Isolation Fiabilité
_id ✓ ✗ ✗ ✗hash(_id) ✓ ✓ ✗ ✗
user ✗ ✓ ✓ ✓user, time ✓ ✓ ✓ ✓
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.insert({…})
Mongos
db.collect.find({…})
Mongos
db.collect.find({…})
Mongos
db.collect.find({…})
Aller plus loin…
https://education.mongodb.com
http://www.meetup.com/Paris-MongoDB-User-Group/
Demo
https://github.com/dwursteisen/atelier-mongodb
Questions ?@dwursteisen
Crédits photos
http://bit.ly/HNvkfZ
http://bit.ly/HGb1BO
http://bit.ly/1d5OVTr
http://bit.ly/1awf0XL
http://bit.ly/MMaRr8
http://bit.ly/1hTARzS
http://bit.ly/1hrvZ7z
http://bit.ly/17SGXwC
http://bit.ly/HNvRP4
http://bit.ly/HGf2Gh
http://bit.ly/1967kv2
http://bit.ly/1c6uCUA