SlideShare ist ein Scribd-Unternehmen logo
1 von 209
Downloaden Sie, um offline zu lesen
Tips and Tricks++ For Indexing
Sanjay Gianchandani,
Senior Consulting Engineer
Sanjay Gianchandani
Senior Consulting Engineer
Sanjay Gianchandani
Senior Consulting Engineer
I identified slow queries.
What index do I make?
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
Equality Sort Range "Rule"
E-S-R
Have you thought about the order of the fields in a compound index?
E-S-R
Have you thought about the order of the fields in a compound index?
Does it really matter?
E-S-R
Have you thought about the order of the fields in a compound index?
The ordering of index keys in a compound index is critically important.
E-S-R provides guidance that is useful in most cases:
• Equality first
• Sort next
• Range last
E-S-R
The ordering of index keys in a compound index is critically important.
E-S-R provides guidance that is useful in most cases:
• Equality first
• Sort next
• Range last
What is the difference between
Equality and Range?
Definitions
Equality Fields
An exact match on a single
value. For example:
• {x:123}
• {x:{$eq:123}}
• {"x.y":123}
Bounds:
"[123.0, 123.0]"
Definitions
Equality Fields Sort
The (entire) requested sort.
.sort({a:1, b:-1})
Bounds:
"[MinKey, MaxKey]",
"[MinKey, MaxKey]"
An exact match on a single
value. For example:
• {x:123}
• {x:{$eq:123}}
• {"x.y":123}
Bounds:
"[123.0, 123.0]"
Definitions
Equality Fields Sort Range Predicates
Any predicates that are not
exact matches. Some
operators include:
• {z:{$gt:9000}}
• {z:{$lte:1000}}
Bounds:
"[9000.0, inf.0]",
The (entire) requested sort.
.sort({a:1, b:-1})
Bounds:
"[MinKey, MaxKey]",
"[MinKey, MaxKey]"
An exact match on a single
value. For example:
• {x:123}
• {x:{$eq:123}}
• {"x.y":123}
Bounds:
"[123.0, 123.0]"
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
Equality
Equality keys are placed first in any order
If present in the query shape,
equality fields should always form the prefix for the index.
Equality
Equality keys are placed first in any order
If present in the query shape,
equality fields should always form the prefix for the index.
Why?
Equality
Equality keys are placed first in any order
If present in the query shape,
equality fields should always form the prefix for the index.
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
Equality
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
If present in the query shape,
equality fields should always form the prefix for the index.
Equality keys are placed first in any order
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
Equality
{gamertag: "Ace", score: 100}
{gamertag: "Ace", score: 99,999}
{gamertag: "Bob", score: 15,000}
{gamertag: "Bob", score: 50,000}
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {}
{}{}
100 15,000 50,000 99,999
Ace Bob Bob Ace
{gamertag: "Ace", score: 100}
{gamertag: "Ace", score: 99,999}
{gamertag: "Bob", score: 15,000}
{gamertag: "Bob", score: 50,000}
Equality
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
100 99,999 15,000 50,000
{} {} {} {}
Equality
100
Ace Bob
99,999 15,000 50,000
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"(9000.0, inf.0]"
],
}
db.games.createIndex({gamertag:1, score:1})
100
Ace Bob
99,999 15,000 50,000
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"(9000.0, inf.0]"
],
}
gamertag
db.games.createIndex({gamertag:1, score:1})
100
Ace Bob
99,999 15,000 50,000
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"(9000.0, inf.0]"
],
}
gamertag
score
db.games.createIndex({gamertag:1, score:1})
100
Ace Bob
99,999 15,000 50,000
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"(9000.0, inf.0]"
],
}
gamertag
score
db.games.createIndex({gamertag:1, score:1})
100
Ace Bob
99,999 15,000 50,000
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"(9000.0, inf.0]"
],
}
gamertag
score
db.games.createIndex({gamertag:1, score:1})
100
Ace Bob
99,999 15,000 50,000
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"(9000.0, inf.0]"
],
}
gamertag
score
db.games.createIndex({gamertag:1, score:1})
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Equality before Range
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
Sort fields are placed next
Placing sort predicates after sequential equality keys allow for the index to:
Provide a non-blocking sort.
Minimize the amount of scanning required.
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Acegamertag
score
db.games.createIndex({score:1, gamertag:1})
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{} {} {} {}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{} {} {} {}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
gamertag
score
db.games.createIndex({score:1, gamertag:1})
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
db.games.createIndex({score:1, gamertag:1})
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
db.games.createIndex({score:1, gamertag:1})
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]”
]
}
db.games.createIndex({score:1, gamertag:1})
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
Ace Bob Bob Ace
100 99,999 15,000 50,000
{1} {2} {} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100
Ace Bob
99,999 15,000 50,000
{}{1} {2} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
”score" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({gamertag:1, score:1})
Sort
100
Ace Bob
99,999 15,000 50,000
{}{1} {2} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
”score" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({gamertag:1, score:1})
Sort
100
Ace Bob
99,999 15,000 50,000
{}{1} {2} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
”score" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({gamertag:1, score:1})
Sort
100
Ace Bob
99,999 15,000 50,000
{}{1} {2} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
”score" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({gamertag:1, score:1})
Sort
100
Ace Bob
99,999 15,000 50,000
{}{1} {2} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
”score" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({gamertag:1, score:1})
Sort
100
Ace Bob
99,999 15,000 50,000
{}{1} {2} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
”score" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({gamertag:1, score:1})
Sort
100
Ace Bob
99,999 15,000 50,000
{}{1} {2} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
”score" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({gamertag:1, score:1})
Sort after Equality
S
E S
E
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Don’t do this, it may require a full index scan
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
Range fields are usually last
This allows them to :
Still participate in filtering the data
But does not force a blocking sort.
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
Range
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Range after Equality
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Range after Equality
Should range come after sort
too?
R
E R
E
Range after Equality
Should range come after sort
too?
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
R
E R
E
Range
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
*
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Bob Ace
*
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {} {} {}{1}{2} {3}
gamertag
score
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
"indexBounds" : {
*,
"score" : [
"(9000.0, inf.0]"
],
"gamertag" : [
"[MinKey, MaxKey]"
]
}
db.games.createIndex({ …, score:1, gamertag:1})
{2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
Blocking SortBlocking Sort
BS
{2}{3}{1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
BS
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
*
Ace Bob Cali Ace
100 15,000 50,00099,999
{} {1} {2} {3}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
*
100 15,000 50,00099,999
Ace Bob Cali
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
db.games.createIndex({ …, gamertag:1, score:1})
{2}
BS
R S
R
S
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range after Sort
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
Operator Type Check
Some operators are simple
$eq: Equality
$gte: Range
Others are trickier
Operator Type Check - Inequality
Inequality Operators: E, S, or R?
• $ne:123
• $nin:[1,2]
Range!
Operator Type Check - Inequality
Inequality Operators: E, S, or R?
• $ne:123
• $nin:[1,2]
Range!
How do you know?
Operator Type Check - Inequality
Inequality Operators: E, S, or R?
• $ne:123
• $nin:[1,2]
Range!
"indexBounds" : {
"x" : [
"[MinKey, 123.0)",
"(123.0, MaxKey]"
]
}
Operator Type Check - Inequality
Range!
"indexBounds" : {
"x" : [
"[MinKey, 123.0)",
"(123.0, MaxKey]"
]
}
50 123 999
Operator Type Check - Inequality
Range!
"indexBounds" : {
"x" : [
"[MinKey, 123.0)",
"(123.0, MaxKey]"
]
}
50 123 999
Operator Type Check - Inequality
Range!
"indexBounds" : {
"x" : [
"[MinKey, 123.0)",
"(123.0, MaxKey]"
]
}
50 123 999
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
planecar racecar
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
planecar racecar
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
planecar racecar
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
p???ecar racecar
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
p???ecar racecar
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry Carpool
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry Carpool
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry Carpool
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry Carpool
Since the regex is left
anchored, can’t we skip
the middle tree?
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry Carpool
Since the regex is left
anchored, can’t we skip
the middle tree?
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
cArrycarry Carpool
Since the regex is left
anchored, can’t we skip
the middle tree?
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
cArrycarry Carpool
Since the regex is left
anchored, can’t we skip
the middle tree?
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
cArrycarry Carpool
Operator Type Check - $in
$in filters: E, S, or R?
• {field:{$in:[1,3]}}
… it depends with respect to key ordering
Alone: a series of Equality matches
Combined: possibly a Range
Operator Type Check - $in
.find({field:{$in:[1,3]}})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
.sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
.sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
.sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
.sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
.sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
.sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
BS
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
.sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
BS
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}})
.sort({sortField:1})
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1}) ?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field" : [
"[3.0, 3.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field" : [
"[3.0, 3.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field" : [
"[3.0, 3.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field" : [
"[3.0, 3.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
?
1 2 3
C G B F A D
db.coll.createIndex({field:1, sortField:1})
Operator Type Check - $in
.find({field:{$in:[1,3]}}).sort({sortField:1})
"indexBounds" : {
"field" : [
"[1.0, 1.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field" : [
"[3.0, 3.0]",
],
"sortField" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
?
1 2 3
C G B F A D
{2} {4} {1} {3}
Sort Merge
db.coll.createIndex({field:1, sortField:1})
BS
S M
Operator Type Check - $in
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
Consecutive Index Keys
Given Indexes:
{gamertag:1, date:1, game:1}
{gamertag:1, game:1, date:1}
Which one is “better”?
It depends on the query shape(s)!
Consider the query:
.find({
gamertag:"Ace",
game: "Halo”
})
Consecutive Index Keys
.find({
gamertag:"Ace",
game: "Halo”
})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
{} {} {} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {} {} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {} {} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {} {} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {} {} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {} {} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {} {} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
{} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
{} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
{} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
{} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
Ace
Mario Halo
2016 2017
Mario Halo
2018 2019
.find({
gamertag:"Ace",
game: "Halo”
})
{} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {}
db.games.createIndex({gamertag:1, date:1, game:1})
Consecutive Index Keys
.find({
gamertag:"Ace",
game: "Halo”
})
{} {} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
Halo
Ace
Mario Halo
2016 2017
Mario
2018 2019
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"game" : [
"["Halo", "Halo"]"
]
}
db.games.createIndex({gamertag:1, game:1})
Ace
2016 2017Mario2018 2019Halo
Consecutive Index Keys
.find({
gamertag:"Ace",
game: "Halo”
})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"game" : [
"["Halo", "Halo"]"
]
}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"game" : [
"["Halo", "Halo"]"
],
"date" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{}{} {}{}
db.games.createIndex({gamertag:1, game:1, date:1})
R
E
E E
E
E
E
Consecutive Index Keys
R
Look familiar? This is equality after range!
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
Exceptions
Is the E-S-R “rule” always optimal?
Nope.
Consider the following query:
db.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {} {1} {2}
db.games.createIndex({gamertag:1, score:1, date:1})
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
db.games.createIndex({gamertag:1, score:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"executionStats" : {
"nReturned" : 2,
"executionTimeMillis" : 23,
"totalKeysExamined" : 9001,
"totalDocsExamined" : 2,
db.games.createIndex({gamertag:1, score:1, date:1})
{1} {2}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
2001 2000 2015 2019 2019
{score:2} {score:1} {score:5000} {score:9001} {score:9000}
… …
gamertag
date
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
… …
2000 2001 2015 2019 2019
{score:2} {score:1} {score:5000} {score:9001} {score:9000}
gamertag
date
db.games.createIndex({gamertag:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
… …
2000 2001 2015 2019 2019
{score:2} {score:1} {score:5000} {score:9001} {score:9000}
gamertag
date
db.games.createIndex({gamertag:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
… …
2000 2001 2015 2019 2019
{score:2} {score:1} {score:5000} {score:9001} {score:9000}
gamertag
date
db.games.createIndex({gamertag:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
… …
2000 2001 2015 2019 2019
{score:2} {score:1} {score:5000} {score:9001} {score:9000}
gamertag
date
db.games.createIndex({gamertag:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
… …
2000 2001 2015 2019 2019
{score:2} {score:1} {score:5000} {score:9001} {score:9000}
gamertag
date
db.games.createIndex({gamertag:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
… …
2000 2001 2015 2019 2019
{score:2} {score:1} {score:5000}
gamertag
date
{score:9001} {score:9000}
BS
"executionStats" : {
"nReturned" : 2,
"executionTimeMillis" : 0,
"totalKeysExamined" : 2,
"totalDocsExamined" : 2,
"executionStats" : {
"nReturned" : 2,
"executionTimeMillis" : 0,
"totalKeysExamined" : 2,
"totalDocsExamined" : 2,
"executionStages" : {
"stage" : "SORT",
"memUsage" : 154,
"memLimit" : 33554432,
db.games.createIndex({gamertag:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}
Exceptions
……… …
BS
S
R
E
R
E
Summary
E-S-R Guidance
A good starting place applicable to
most use cases
Place keys in the following order:
Equality first
Sort next
Range last
Remember:
• Some operators may be range
instead of equality
• Having consecutive keys used in
the index is important
• Specifics about your data set may
need a different approach
Thank You!
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing MongoDB

Weitere ähnliche Inhalte

Ähnlich wie MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing MongoDB

Python advanced 2. regular expression in python
Python advanced 2. regular expression in pythonPython advanced 2. regular expression in python
Python advanced 2. regular expression in python
John(Qiang) Zhang
 
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptxACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ssuser1eba67
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
Vincent Pradeilles
 

Ähnlich wie MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing MongoDB (17)

MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDBMongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
 
MongoDB World 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB World 2019: Tips and Tricks++ for Querying and Indexing MongoDBMongoDB World 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB World 2019: Tips and Tricks++ for Querying and Indexing MongoDB
 
MongoDB .local Toronto 2019: Tips and Tricks for Effective Indexing
MongoDB .local Toronto 2019: Tips and Tricks for Effective IndexingMongoDB .local Toronto 2019: Tips and Tricks for Effective Indexing
MongoDB .local Toronto 2019: Tips and Tricks for Effective Indexing
 
Avoid Query Pitfalls
Avoid Query PitfallsAvoid Query Pitfalls
Avoid Query Pitfalls
 
MongoDB.local Dallas 2019: Tips & Tricks for Avoiding Common Query Pitfalls
MongoDB.local Dallas 2019: Tips & Tricks for Avoiding Common Query PitfallsMongoDB.local Dallas 2019: Tips & Tricks for Avoiding Common Query Pitfalls
MongoDB.local Dallas 2019: Tips & Tricks for Avoiding Common Query Pitfalls
 
MongoDB.local Seattle 2019: Tips & Tricks for Avoiding Common Query Pitfalls
MongoDB.local Seattle 2019: Tips & Tricks for Avoiding Common Query PitfallsMongoDB.local Seattle 2019: Tips & Tricks for Avoiding Common Query Pitfalls
MongoDB.local Seattle 2019: Tips & Tricks for Avoiding Common Query Pitfalls
 
Tips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
Tips and Tricks for Avoiding Common Query Pitfalls Christian KurzeTips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
Tips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
 
MongoDB .local Munich 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local Munich 2019: Tips and Tricks++ for Querying and Indexing MongoDBMongoDB .local Munich 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local Munich 2019: Tips and Tricks++ for Querying and Indexing MongoDB
 
MongoDB World 2019: How to Keep an Average API Response Time Less than 5ms wi...
MongoDB World 2019: How to Keep an Average API Response Time Less than 5ms wi...MongoDB World 2019: How to Keep an Average API Response Time Less than 5ms wi...
MongoDB World 2019: How to Keep an Average API Response Time Less than 5ms wi...
 
Fazendo mágica com ElasticSearch
Fazendo mágica com ElasticSearchFazendo mágica com ElasticSearch
Fazendo mágica com ElasticSearch
 
Casting for not so strange actors
Casting for not so strange actorsCasting for not so strange actors
Casting for not so strange actors
 
Python advanced 2. regular expression in python
Python advanced 2. regular expression in pythonPython advanced 2. regular expression in python
Python advanced 2. regular expression in python
 
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptxACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
ACI-Webinar-3-MinMaxAlphaBetaPruning-TicTacToe.pptx
 
How to win $10m - analysing DOTA2 data in R (Sheffield R Users Group - May)
How to win $10m - analysing DOTA2 data in R (Sheffield R Users Group - May)How to win $10m - analysing DOTA2 data in R (Sheffield R Users Group - May)
How to win $10m - analysing DOTA2 data in R (Sheffield R Users Group - May)
 
Optimizing Cypher Queries in Neo4j
Optimizing Cypher Queries in Neo4jOptimizing Cypher Queries in Neo4j
Optimizing Cypher Queries in Neo4j
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
 
Regex 101
Regex 101Regex 101
Regex 101
 

Mehr von MongoDB

Mehr von MongoDB (20)

MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Migrate Anything* to MongoDB AtlasMongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
 
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
 
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
 
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDBMongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
 
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
 
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series DataMongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
 
MongoDB SoCal 2020: MongoDB Atlas Jump Start
 MongoDB SoCal 2020: MongoDB Atlas Jump Start MongoDB SoCal 2020: MongoDB Atlas Jump Start
MongoDB SoCal 2020: MongoDB Atlas Jump Start
 
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
 
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
 
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
 
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
 
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your MindsetMongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
 
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: MongoDB Atlas JumpstartMongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
 
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
 
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
 
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep DiveMongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
 
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & GolangMongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
 
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
 
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
 
MongoDB .local Paris 2020: Les bonnes pratiques pour sécuriser MongoDB
MongoDB .local Paris 2020: Les bonnes pratiques pour sécuriser MongoDBMongoDB .local Paris 2020: Les bonnes pratiques pour sécuriser MongoDB
MongoDB .local Paris 2020: Les bonnes pratiques pour sécuriser MongoDB
 

Kürzlich hochgeladen

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Kürzlich hochgeladen (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 

MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing MongoDB

  • 1.
  • 2. Tips and Tricks++ For Indexing Sanjay Gianchandani, Senior Consulting Engineer
  • 4. Sanjay Gianchandani Senior Consulting Engineer I identified slow queries. What index do I make?
  • 5. Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 6. Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 8. E-S-R Have you thought about the order of the fields in a compound index?
  • 9. E-S-R Have you thought about the order of the fields in a compound index? Does it really matter?
  • 10. E-S-R Have you thought about the order of the fields in a compound index? The ordering of index keys in a compound index is critically important. E-S-R provides guidance that is useful in most cases: • Equality first • Sort next • Range last
  • 11. E-S-R The ordering of index keys in a compound index is critically important. E-S-R provides guidance that is useful in most cases: • Equality first • Sort next • Range last What is the difference between Equality and Range?
  • 12. Definitions Equality Fields An exact match on a single value. For example: • {x:123} • {x:{$eq:123}} • {"x.y":123} Bounds: "[123.0, 123.0]"
  • 13. Definitions Equality Fields Sort The (entire) requested sort. .sort({a:1, b:-1}) Bounds: "[MinKey, MaxKey]", "[MinKey, MaxKey]" An exact match on a single value. For example: • {x:123} • {x:{$eq:123}} • {"x.y":123} Bounds: "[123.0, 123.0]"
  • 14. Definitions Equality Fields Sort Range Predicates Any predicates that are not exact matches. Some operators include: • {z:{$gt:9000}} • {z:{$lte:1000}} Bounds: "[9000.0, inf.0]", The (entire) requested sort. .sort({a:1, b:-1}) Bounds: "[MinKey, MaxKey]", "[MinKey, MaxKey]" An exact match on a single value. For example: • {x:123} • {x:{$eq:123}} • {"x.y":123} Bounds: "[123.0, 123.0]"
  • 15. Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 16. Equality Equality keys are placed first in any order If present in the query shape, equality fields should always form the prefix for the index.
  • 17. Equality Equality keys are placed first in any order If present in the query shape, equality fields should always form the prefix for the index. Why?
  • 18. Equality Equality keys are placed first in any order If present in the query shape, equality fields should always form the prefix for the index. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
  • 19. Equality db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) If present in the query shape, equality fields should always form the prefix for the index. Equality keys are placed first in any order
  • 20. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) Equality {gamertag: "Ace", score: 100} {gamertag: "Ace", score: 99,999} {gamertag: "Bob", score: 15,000} {gamertag: "Bob", score: 50,000}
  • 21. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {}{} 100 15,000 50,000 99,999 Ace Bob Bob Ace {gamertag: "Ace", score: 100} {gamertag: "Ace", score: 99,999} {gamertag: "Bob", score: 15,000} {gamertag: "Bob", score: 50,000} Equality
  • 22. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } db.games.createIndex({score:1, gamertag:1})
  • 23. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag db.games.createIndex({score:1, gamertag:1})
  • 24. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 25. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 26. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 27. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 28. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 29. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 30. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 31. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 32. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality
  • 33. Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) 100 99,999 15,000 50,000 {} {} {} {} Equality
  • 34. 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } db.games.createIndex({gamertag:1, score:1})
  • 35. 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } gamertag db.games.createIndex({gamertag:1, score:1})
  • 36. 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } gamertag score db.games.createIndex({gamertag:1, score:1})
  • 37. 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } gamertag score db.games.createIndex({gamertag:1, score:1})
  • 38. 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } gamertag score db.games.createIndex({gamertag:1, score:1})
  • 39. 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } gamertag score db.games.createIndex({gamertag:1, score:1})
  • 40. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Equality before Range
  • 41. Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 42. Sort fields are placed next Placing sort predicates after sequential equality keys allow for the index to: Provide a non-blocking sort. Minimize the amount of scanning required. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort
  • 43. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Acegamertag score db.games.createIndex({score:1, gamertag:1})
  • 44. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {} {} {} {} gamertag score db.games.createIndex({score:1, gamertag:1})
  • 45. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {} {} {} {} gamertag score db.games.createIndex({score:1, gamertag:1})
  • 46. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} gamertag score db.games.createIndex({score:1, gamertag:1})
  • 47. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } db.games.createIndex({score:1, gamertag:1})
  • 48. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } db.games.createIndex({score:1, gamertag:1})
  • 49. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 50. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 51. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 52. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 53. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 54. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 55. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 56. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 57. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 58. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 59. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
  • 60. Sort Ace Bob Bob Ace 100 99,999 15,000 50,000 {1} {2} {} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
  • 61. Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 62. Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 63. Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 64. Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 65. Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 66. Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 67. Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 68. Sort after Equality S E S E db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Don’t do this, it may require a full index scan
  • 69. Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 70. Range fields are usually last This allows them to : Still participate in filtering the data But does not force a blocking sort. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) Range
  • 71. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Range after Equality
  • 72. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Range after Equality Should range come after sort too?
  • 73. R E R E Range after Equality Should range come after sort too? db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
  • 74. R E R E Range db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
  • 75. 100 15,000 50,000 99,999 Ace Bob Bob Ace * db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score db.games.createIndex({ …, score:1, gamertag:1})
  • 76. 100 15,000 50,000 99,999 Ace Bob Bob Ace * db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score db.games.createIndex({ …, score:1, gamertag:1})
  • 77. 100 15,000 50,000 99,999 Ace Bob Cali Ace * db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score db.games.createIndex({ …, score:1, gamertag:1})
  • 78. 100 15,000 50,000 99,999 Ace Bob Cali Ace * db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {} {} {}{1}{2} {3} gamertag score db.games.createIndex({ …, score:1, gamertag:1})
  • 79. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 80. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 81. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 82. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 83. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 84. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 85. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 86. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 87. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 88. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 89. {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range Blocking SortBlocking Sort BS
  • 90. {2}{3}{1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range BS
  • 91. 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range
  • 92. db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range * Ace Bob Cali Ace 100 15,000 50,00099,999 {} {1} {2} {3}
  • 93. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 94. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 95. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 96. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 97. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 98. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 99. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 100. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 101. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 102. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 103. * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 104. BS R S R S db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range after Sort
  • 105. Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 106. Operator Type Check Some operators are simple $eq: Equality $gte: Range Others are trickier
  • 107. Operator Type Check - Inequality Inequality Operators: E, S, or R? • $ne:123 • $nin:[1,2] Range!
  • 108. Operator Type Check - Inequality Inequality Operators: E, S, or R? • $ne:123 • $nin:[1,2] Range! How do you know?
  • 109. Operator Type Check - Inequality Inequality Operators: E, S, or R? • $ne:123 • $nin:[1,2] Range! "indexBounds" : { "x" : [ "[MinKey, 123.0)", "(123.0, MaxKey]" ] }
  • 110. Operator Type Check - Inequality Range! "indexBounds" : { "x" : [ "[MinKey, 123.0)", "(123.0, MaxKey]" ] } 50 123 999
  • 111. Operator Type Check - Inequality Range! "indexBounds" : { "x" : [ "[MinKey, 123.0)", "(123.0, MaxKey]" ] } 50 123 999
  • 112. Operator Type Check - Inequality Range! "indexBounds" : { "x" : [ "[MinKey, 123.0)", "(123.0, MaxKey]" ] } 50 123 999
  • 113. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range!
  • 114. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range!
  • 115. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! planecar racecar
  • 116. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! planecar racecar
  • 117. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! planecar racecar
  • 118. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! p???ecar racecar
  • 119. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! p???ecar racecar
  • 120. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range!
  • 121. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry
  • 122. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry
  • 123. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry Carpool
  • 124. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry Carpool
  • 125. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry Carpool
  • 126. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry Carpool Since the regex is left anchored, can’t we skip the middle tree?
  • 127. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry Carpool Since the regex is left anchored, can’t we skip the middle tree?
  • 128. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! cArrycarry Carpool Since the regex is left anchored, can’t we skip the middle tree?
  • 129. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! cArrycarry Carpool Since the regex is left anchored, can’t we skip the middle tree?
  • 130. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! cArrycarry Carpool
  • 131. Operator Type Check - $in $in filters: E, S, or R? • {field:{$in:[1,3]}} … it depends with respect to key ordering Alone: a series of Equality matches Combined: possibly a Range
  • 132. Operator Type Check - $in .find({field:{$in:[1,3]}})
  • 133. Operator Type Check - $in .find({field:{$in:[1,3]}}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 134. Operator Type Check - $in .find({field:{$in:[1,3]}}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 135. Operator Type Check - $in .find({field:{$in:[1,3]}}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 136. Operator Type Check - $in .find({field:{$in:[1,3]}}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 137. Operator Type Check - $in .find({field:{$in:[1,3]}}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 138. Operator Type Check - $in .find({field:{$in:[1,3]}}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 139. Operator Type Check - $in .find({field:{$in:[1,3]}}) .sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 140. Operator Type Check - $in .find({field:{$in:[1,3]}}) .sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 141. Operator Type Check - $in .find({field:{$in:[1,3]}}) .sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 142. Operator Type Check - $in .find({field:{$in:[1,3]}}) .sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 143. Operator Type Check - $in .find({field:{$in:[1,3]}}) .sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 144. Operator Type Check - $in .find({field:{$in:[1,3]}}) .sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D BS db.coll.createIndex({field:1, sortField:1})
  • 145. Operator Type Check - $in .find({field:{$in:[1,3]}}) .sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D BS db.coll.createIndex({field:1, sortField:1})
  • 146. Operator Type Check - $in .find({field:{$in:[1,3]}}) .sort({sortField:1}) ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 147. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 148. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 149. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 150. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 151. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 152. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 153. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field" : [ "[3.0, 3.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 154. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field" : [ "[3.0, 3.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 155. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field" : [ "[3.0, 3.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 156. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field" : [ "[3.0, 3.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D ? 1 2 3 C G B F A D db.coll.createIndex({field:1, sortField:1})
  • 157. Operator Type Check - $in .find({field:{$in:[1,3]}}).sort({sortField:1}) "indexBounds" : { "field" : [ "[1.0, 1.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field" : [ "[3.0, 3.0]", ], "sortField" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D ? 1 2 3 C G B F A D {2} {4} {1} {3} Sort Merge db.coll.createIndex({field:1, sortField:1})
  • 158. BS S M Operator Type Check - $in
  • 159. Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 160. Consecutive Index Keys Given Indexes: {gamertag:1, date:1, game:1} {gamertag:1, game:1, date:1} Which one is “better”? It depends on the query shape(s)! Consider the query: .find({ gamertag:"Ace", game: "Halo” })
  • 162. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) db.games.createIndex({gamertag:1, date:1, game:1})
  • 163. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 164. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 165. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 166. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 167. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 168. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 169. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 170. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 171. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 172. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 173. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 174. Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 175. Consecutive Index Keys .find({ gamertag:"Ace", game: "Halo” }) {} {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } Halo Ace Mario Halo 2016 2017 Mario 2018 2019 "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "game" : [ "["Halo", "Halo"]" ] } db.games.createIndex({gamertag:1, game:1})
  • 176. Ace 2016 2017Mario2018 2019Halo Consecutive Index Keys .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "game" : [ "["Halo", "Halo"]" ] } "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "game" : [ "["Halo", "Halo"]" ], "date" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "game" : [ "["Halo", "Halo"]" ] } {}{} {}{} db.games.createIndex({gamertag:1, game:1, date:1})
  • 177. R E E E E E E Consecutive Index Keys R Look familiar? This is equality after range!
  • 178. Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 179. Exceptions Is the E-S-R “rule” always optimal? Nope. Consider the following query: db.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1})
  • 180. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} {1} {2} db.games.createIndex({gamertag:1, score:1, date:1})
  • 181. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 182. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 183. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 184. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 185. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 186. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 187. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 188. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 189. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 190. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 191. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 192. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 193. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 194. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} db.games.createIndex({gamertag:1, score:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2}
  • 195. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} "executionStats" : { "nReturned" : 2, "executionTimeMillis" : 23, "totalKeysExamined" : 9001, "totalDocsExamined" : 2, db.games.createIndex({gamertag:1, score:1, date:1}) {1} {2}
  • 197. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 2001 2000 2015 2019 2019 {score:2} {score:1} {score:5000} {score:9001} {score:9000} … … gamertag date
  • 198. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace … … 2000 2001 2015 2019 2019 {score:2} {score:1} {score:5000} {score:9001} {score:9000} gamertag date db.games.createIndex({gamertag:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }
  • 199. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace … … 2000 2001 2015 2019 2019 {score:2} {score:1} {score:5000} {score:9001} {score:9000} gamertag date db.games.createIndex({gamertag:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }
  • 200. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace … … 2000 2001 2015 2019 2019 {score:2} {score:1} {score:5000} {score:9001} {score:9000} gamertag date db.games.createIndex({gamertag:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }
  • 201. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace … … 2000 2001 2015 2019 2019 {score:2} {score:1} {score:5000} {score:9001} {score:9000} gamertag date db.games.createIndex({gamertag:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }
  • 202. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace … … 2000 2001 2015 2019 2019 {score:2} {score:1} {score:5000} {score:9001} {score:9000} gamertag date db.games.createIndex({gamertag:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }
  • 203. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace … … 2000 2001 2015 2019 2019 {score:2} {score:1} {score:5000} gamertag date {score:9001} {score:9000} BS "executionStats" : { "nReturned" : 2, "executionTimeMillis" : 0, "totalKeysExamined" : 2, "totalDocsExamined" : 2, "executionStats" : { "nReturned" : 2, "executionTimeMillis" : 0, "totalKeysExamined" : 2, "totalDocsExamined" : 2, "executionStages" : { "stage" : "SORT", "memUsage" : 154, "memLimit" : 33554432, db.games.createIndex({gamertag:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }
  • 206. E-S-R Guidance A good starting place applicable to most use cases Place keys in the following order: Equality first Sort next Range last Remember: • Some operators may be range instead of equality • Having consecutive keys used in the index is important • Specifics about your data set may need a different approach