featuring special guest Sean Bean
Let’s talk about production 
MongoDB 
Database Happiness 
Developer Fun
But it doesn’t need to be 
this way.
Let’s use House Stark as an 
example
It starts with the data model 
_id name home p_id 
0 Ned Stark Winterfell 0 
1 Arya Stark Winterfell 1 
2 Bran Stark Winterfell 2 
p_id proficiencies 
0 
keeping a cool 
head 
1 
pulling off the short 
hair look 
2 riding piggyback
Arrays in MongoDB 
{ 
_id: ObjectId(“000”), 
name: “Ned Stark”, 
relatives: [ 
ObjectId(“001”), 
ObjectId(“002”) 
] 
} 
{ 
_id: ObjectId(“000”), 
name: “Ned Stark”, 
relatives: [ 
{ 
_id: ObjectId(“001”), 
name: “Arya Stark”, 
… 
}, 
{ 
_id: ObjectId(“002”), 
name: “Bran Stark”, 
… 
} 
] 
} 
vs.
What are “total normalization” 
trade-offs? 
{ 
_id: ObjectId(“000”), 
name: “Ned Stark”, 
relatives: [ 
ObjectId(“001”), 
ObjectId(“002”) 
] 
}
Here is Ned Stark. 
His relatives are: 
ObjectId(“001”) ObjectId(“002”)
And “partial denormalization”? 
{ 
_id: ObjectId(“000”), 
name: “Ned Stark”, 
relatives: [ 
{ 
_id: ObjectId(“001”), 
name: “Arya Stark”, 
img: “../arya.png” 
} 
{ 
_id: ObjectId(“002”), 
name: “Bran Stark”, 
img: “../bran.png” 
} 
] 
}
Here is Ned Stark. 
His relatives are: 
Arya Stark Bran Stark
Rules on Arrays 
High reads, low updates/writes 
Array should be bound in size 
Don’t need to frequently access 
embedded items individually
#1 cause of slow databases: 
(lack of) indexes
cursor.explain() tells us if we’re 
indexed 
{ 
"cursor" : "<Cursor Type and Index>", 
"n" : <num>, 
"nscannedObjects" : <num>, 
"nscanned" : <num>, 
"nscannedObjectsAllPlans" : <num>, 
"nscannedAllPlans" : <num>, 
"scanAndOrder" : <boolean>, 
"indexOnly" : <boolean>, 
"millis" : <num>, 
"indexBounds" : { <index bounds> }, 
"allPlans" : [ 
{ "cursor" : "<Cursor Type and Index>", 
"n" : <num>, 
"nscannedObjects" : <num>, 
"nscanned" : <num>, 
"indexBounds" : { <index bounds> } 
}, 
... 
] 
}
Remember our indexing 
essentials 
scanAndOrder 
n vs nScanned 
NO BasicCursor!!!!!!!!!!!!! NO! 
Tier 3 
Tier 2 
Tier 1
How to save your database 
• mongod logs 
• db.currentOp() & db.killOp()
There’s lots of good info in the 
logs 
• 2014-10-09T02:26:58.994-0700 [conn367784] query gotDB.people query: { 
$query: { isAlive: true }, $orderby: { age: 1 } } planSummary: IXSCAN { isAlive: 
1 }, cursorid:1736436984952 ntoreturn:10 ntoskip:0 nscanned:7677 
nscannedObjects:7677 scanAndOrder:1 keyUpdates:0 numYields:0 
locks(micros) r:115557 nreturned:10 reslen:34036 115ms 
• 2014-10-09T21:26:58.994-0700 [conn127156] command gotDB.$cmd 
command: mapReduce { $msg: "query not recording (too large)" } 
planSummary: COLLSCAN keyUpdates:0 numYields:3843 locks(micros) 
W:2840 r:85085260 w:26899 reslen:187 76657ms
Use currentOp() to triage slow 
operations 
db.currentOp().inprog.forEach( 
function(op) { 
if(op.secs_running > 5) printjson(op); 
} 
)
Terminate slowness 
{ 
"locks": { 
"^myDB": "R" 
}, 
"ns": "myDB.bar", 
"op": "query", 
"opid": 1344808, 
"query": {}, 
"secs_running": 53, 
"waitingForLock": false 
} 
db.killOp(1344808)
Thanks for listening! 
chris@mongolab.com 
@chrisckchang 
@mongolab

Running Production MongoDB Lightning Talk

  • 1.
  • 2.
    Let’s talk aboutproduction MongoDB Database Happiness Developer Fun
  • 3.
    But it doesn’tneed to be this way.
  • 4.
    Let’s use HouseStark as an example
  • 5.
    It starts withthe data model _id name home p_id 0 Ned Stark Winterfell 0 1 Arya Stark Winterfell 1 2 Bran Stark Winterfell 2 p_id proficiencies 0 keeping a cool head 1 pulling off the short hair look 2 riding piggyback
  • 6.
    Arrays in MongoDB { _id: ObjectId(“000”), name: “Ned Stark”, relatives: [ ObjectId(“001”), ObjectId(“002”) ] } { _id: ObjectId(“000”), name: “Ned Stark”, relatives: [ { _id: ObjectId(“001”), name: “Arya Stark”, … }, { _id: ObjectId(“002”), name: “Bran Stark”, … } ] } vs.
  • 7.
    What are “totalnormalization” trade-offs? { _id: ObjectId(“000”), name: “Ned Stark”, relatives: [ ObjectId(“001”), ObjectId(“002”) ] }
  • 8.
    Here is NedStark. His relatives are: ObjectId(“001”) ObjectId(“002”)
  • 9.
    And “partial denormalization”? { _id: ObjectId(“000”), name: “Ned Stark”, relatives: [ { _id: ObjectId(“001”), name: “Arya Stark”, img: “../arya.png” } { _id: ObjectId(“002”), name: “Bran Stark”, img: “../bran.png” } ] }
  • 10.
    Here is NedStark. His relatives are: Arya Stark Bran Stark
  • 11.
    Rules on Arrays High reads, low updates/writes Array should be bound in size Don’t need to frequently access embedded items individually
  • 12.
    #1 cause ofslow databases: (lack of) indexes
  • 13.
    cursor.explain() tells usif we’re indexed { "cursor" : "<Cursor Type and Index>", "n" : <num>, "nscannedObjects" : <num>, "nscanned" : <num>, "nscannedObjectsAllPlans" : <num>, "nscannedAllPlans" : <num>, "scanAndOrder" : <boolean>, "indexOnly" : <boolean>, "millis" : <num>, "indexBounds" : { <index bounds> }, "allPlans" : [ { "cursor" : "<Cursor Type and Index>", "n" : <num>, "nscannedObjects" : <num>, "nscanned" : <num>, "indexBounds" : { <index bounds> } }, ... ] }
  • 14.
    Remember our indexing essentials scanAndOrder n vs nScanned NO BasicCursor!!!!!!!!!!!!! NO! Tier 3 Tier 2 Tier 1
  • 16.
    How to saveyour database • mongod logs • db.currentOp() & db.killOp()
  • 17.
    There’s lots ofgood info in the logs • 2014-10-09T02:26:58.994-0700 [conn367784] query gotDB.people query: { $query: { isAlive: true }, $orderby: { age: 1 } } planSummary: IXSCAN { isAlive: 1 }, cursorid:1736436984952 ntoreturn:10 ntoskip:0 nscanned:7677 nscannedObjects:7677 scanAndOrder:1 keyUpdates:0 numYields:0 locks(micros) r:115557 nreturned:10 reslen:34036 115ms • 2014-10-09T21:26:58.994-0700 [conn127156] command gotDB.$cmd command: mapReduce { $msg: "query not recording (too large)" } planSummary: COLLSCAN keyUpdates:0 numYields:3843 locks(micros) W:2840 r:85085260 w:26899 reslen:187 76657ms
  • 18.
    Use currentOp() totriage slow operations db.currentOp().inprog.forEach( function(op) { if(op.secs_running > 5) printjson(op); } )
  • 19.
    Terminate slowness { "locks": { "^myDB": "R" }, "ns": "myDB.bar", "op": "query", "opid": 1344808, "query": {}, "secs_running": 53, "waitingForLock": false } db.killOp(1344808)
  • 20.
    Thanks for listening! chris@mongolab.com @chrisckchang @mongolab

Editor's Notes

  • #12 query too large
  • #18 note 2.6 logs check to see connections are authenticating, where connections are coming from, what operations are slow, etc. what’s going on to my database right now