SlideShare uma empresa Scribd logo
1 de 205
Baixar para ler offline
Tips and Tricks++
for Indexing MongoDB
Ronán Bohan
Principal Solutions Architect, EMEA
v 20190922
Introductions
{
name : “Ronán Bohan”,
role : “Principal Solutions Architect”
}
Introductions
I’ve identified some slow queries.
What indexes do I create?
Introductions
For that we’re going to look at
compound indexes and
the “E-S-R” rule
Roadmap
E-S-R Overview
Deep dive:
• Equality
• Sort
• Range
E-S-R Considerations
Operator Type Checks
Exceptions?
Equality Sort Range "Rule"
E-S-R
The ordering of index keys in a compound index is critically important.
E-S-R
The ordering of index keys in a compound index is critically important.
Sure, but does it really matter?
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
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?
Equality Fields
Definitions
An exact match on a single
value. For example:
• {x:123}
• {x:{$eq:123}}
• {"x.y":123}
Bounds:
"[123.0, 123.0]"
Sort Range Predicates
Definitions
Sort
The (entire) requested sort.
.sort({a:1})
.sort({a:1, b:-1})
An exact match on a single
value. For example:
• {x:123}
• {x:{$eq:123}}
• {"x.y":123}
Bounds:
"[123.0, 123.0]"
Bounds:
"[MinKey, MaxKey]"
Range PredicatesEquality Fields
"[MinKey, MaxKey]",
"[MinKey, MaxKey]"
Definitions
Sort Range Predicates
Any predicates that are not
exact matches. Some
operators include:
• {z:{$gt:9000}}
• {foo:{$lte:1000}}
The (entire) requested sort.
.sort({a:1})
.sort({a:1, b:-1})
An exact match on a single
value. For example:
• {x:123}
• {x:{$eq:123}}
• {"x.y":123}
Bounds:
"[123.0, 123.0]"
Bounds:
"[MinKey, MaxKey]",
"[MinKey, MaxKey]"
Bounds:
"(9000.0, inf.0]"
"[-inf.0, 1000]"
Equality Fields
Roadmap
E-S-R Overview
Deep dive:
• Equality
• Sort
• Range
E-S-R Considerations
Operator Type Checks
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}
99,999
{gamertag: "Bob", score: 15,000}{gamertag: "Ace", score: 100}
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {}
{}{}
100 15,000 50,000
Ace Bob Bob Ace
{gamertag: "Ace", score: 99,999} {gamertag: "Bob", score: 50,000}
Equality
db.games.createIndex({score:1, gamertag:1})
gamertag
score
ANTI-pattern index:
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})
gamertag
score
ANTI-pattern index:
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})
gamertag
score
ANTI-pattern index:
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})ANTI-pattern index:
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})ANTI-pattern index:
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})ANTI-pattern index:
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})ANTI-pattern index:
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})ANTI-pattern index:
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})ANTI-pattern index:
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})ANTI-pattern index:
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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
Equality
db.games.createIndex({gamertag:1, score:1})Recommended index:
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
100 99,999 15,000 50,000
{} {} {} {}
Equality
db.games.createIndex({gamertag:1, score:1})
gamertag
score
Recommended index:
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})
gamertag
score
Recommended index:
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})
score
Recommended index:
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})Recommended index:
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})Recommended index:
100
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
Ace
db.games.createIndex({gamertag:1, score:1})Recommended index:
100
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
Ace
✓
db.games.createIndex({gamertag:1, score:1})Recommended index:
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Equality before Range
Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Equality before Range
Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
Hey! Don’t forget about your
demo!!
Roadmap
E-S-R Overview
Deep dive:
• Equality
• Sort
• Range
E-S-R Considerations
Operator Type Checks
Exceptions?
Sort fields are placed next
Placing sort predicates after sequential equality keys allows 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
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{} {} {} {}
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{} {} {} {}
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{} {} {} {}
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
gamertag
score
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Acegamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Acegamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Acegamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
✓
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
✓
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
✓
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
✓
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
✓
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
✓
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"score" : [
"[MinKey, MaxKey]"
],
"gamertag" : [
"["Ace", "Ace"]"
]
}
{1} {} {} {2}
✓✓
db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
db.games.createIndex({gamertag:1, score:1})Recommended index:
Sort
Ace Bob Bob Ace
100 99,999 15,000 50,000
{1} {2} {} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
db.games.createIndex({gamertag:1, score:1})
gamertag
score
Recommended index:
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})Recommended index:
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})Recommended index:
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})Recommended index:
Sort
100
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]"
]
}
Ace
db.games.createIndex({gamertag:1, score:1})Recommended index:
Sort
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]"
]
}
100
Ace
✓
db.games.createIndex({gamertag:1, score:1})Recommended index:
Sort
Bob
15,000 50,000
{}{1} {2} {}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
gamertag
score
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
]
}
100 99,999
Ace
✓ ✓
db.games.createIndex({gamertag:1, score:1})Recommended index:
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
Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
Roadmap
E-S-R Overview
Deep dive:
• Equality
• Sort
• Range
E-S-R Considerations
Operator Type Checks
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}} )
Range
Haven’t we seen this before?
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Range after Equality
Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Range
But should range come after
sort too?
Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
R
E R
E
Range
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
But should range come after
sort too?
Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
R
E R
E
Range
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
But should range come after
sort too?
Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
db.games.createIndex({…, score:1, gamertag:1})ANTI-pattern index:
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})ANTI-pattern index:
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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal Ace
*
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
gamertag
score
db.games.createIndex({…, score:1, gamertag:1})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal Ace
*
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {} {} {}{1}{2} {3}
gamertag
score
db.games.createIndex({…, score:1, gamertag:1})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
100 15,000 50,000 99,999
Ace Bob Cal 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})ANTI-pattern index:
{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
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,000 99,999
Ace Bob Cal Ace
*
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
*
Ace Bob Cal Ace
100 15,000 50,00099,999
{} {1} {2} {3}
db.games.createIndex({…, gamertag:1, score:1})
score
gamertag
Recommended index:
*
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
*
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
*
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
*
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
*
✓
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
*
✓
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
*
✓ ✓
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
*
✓ ✓
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
*
✓ ✓ ✓
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
100 15,000 50,00099,999
Ace Bob Cal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
{} {1} {3}
score
gamertag
"indexBounds" : {
*,
"gamertag" : [
"[MinKey, MaxKey]"
]
"score" : [
"(9000.0, inf.0]"
]
}
{2}
*
db.games.createIndex({…, gamertag:1, score:1})Recommended index:
BS
R S
R
S
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range after Sort
Index: {…, gamertag:1, score:1}
Index: {…, score:1, gamertag:1}
Roadmap
E-S-R Overview
Deep dive:
• Equality
• Sort
• Range
E-S-R Considerations
Operator Type Checks
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 zebra
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry zebra
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!
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 query shape
and key ordering
Alone: a series of Equality matches
Combined: possibly a Range
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
db.coll.createIndex({field1:1, field2:1})
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
2
C G B F A D
db.coll.createIndex({field1:1, field2:1})
?
1 3
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
2
C G B F A D
db.coll.createIndex({field1:1, field2:1})
?
31
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
2
C G B F A D
db.coll.createIndex({field1:1, field2:1})
?
31
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
2
C G B F A D
db.coll.createIndex({field1:1, field2:1})
?
31
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
2
C G B F A D
db.coll.createIndex({field1:1, field2:1})
1 3
?
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
1 2 3
C G B F A D
db.coll.createIndex({field1:1, field2:1})
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
.sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
]
}
?
2
C G B F A D
db.coll.createIndex({field1:1, field2:1})
1 3
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
.sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"field2" : [
"[MinKey, MaxKey]"
]
}
?
2
C G B F A D
1 3
db.coll.createIndex({field1:1, field2:1})
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
.sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"field2" : [
"[MinKey, MaxKey]"
]
}
?
2
C G B F A D
1 3
db.coll.createIndex({field1:1, field2:1})
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
.sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"field2" : [
"[MinKey, MaxKey]"
]
}
?
2
C G B F A D
1 3
db.coll.createIndex({field1:1, field2:1})
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
.sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"field2" : [
"[MinKey, MaxKey]"
]
}
?
2
C G B F A D
BS
1 3
db.coll.createIndex({field1:1, field2:1})
Operator Type Check - $in
.find({field1:{$in:[1,3]}})
.sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
"[3.0, 3.0]"
],
"field2" : [
"[MinKey, MaxKey]"
]
}
?
1 2 3
C G B F A D
BS
db.coll.createIndex({field1:1, field2:1})
Operator Type Check - $in
db.coll.createIndex({field1:1, field2:1})
.find({field1:{$in:[1,3]}}).sort({field2:1})
.find({field1:{$in:[1,3]}}).sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
Operator Type Check - $in
2 3
C G B F A D
db.coll.createIndex({field1:1, field2:1})
?
1
.find({field1:{$in:[1,3]}}).sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
Operator Type Check - $in
2 3
C G B F A D
db.coll.createIndex({field1:1, field2:1})
1
?
.find({field1:{$in:[1,3]}}).sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
Operator Type Check - $in
2 3
C G B F A D
db.coll.createIndex({field1:1, field2:1})
?
1
.find({field1:{$in:[1,3]}}).sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
Operator Type Check - $in
2 3
C G B F A D
db.coll.createIndex({field1:1, field2:1})
?
1
.find({field1:{$in:[1,3]}}).sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field1" : [
"[3.0, 3.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
Operator Type Check - $in
2 3
C G B F A D
?
1 2 3
C G B F A D
db.coll.createIndex({field1:1, field2:1})
?
1
.find({field1:{$in:[1,3]}}).sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field1" : [
"[3.0, 3.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
Operator Type Check - $in
1 2 3
C G B F A D
1 2 3
C G B F A D
db.coll.createIndex({field1:1, field2:1})
? ?
.find({field1:{$in:[1,3]}}).sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field1" : [
"[3.0, 3.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
Operator Type Check - $in
2 3
C G B F A D
1 2
C G B F A D
db.coll.createIndex({field1:1, field2:1})
3
?
1
?
.find({field1:{$in:[1,3]}}).sort({field2:1})
"indexBounds" : {
"field1" : [
"[1.0, 1.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
"indexBounds" : {
"field1" : [
"[3.0, 3.0]",
],
"field2" : [
"[MinKey, MaxKey]"
]
}
Operator Type Check - $in
2 3
C G B F A D
1 2
C G B F A D
{2} {4} {1} {3}
Sort Merge
db.coll.createIndex({field1:1, field2:1})
?
1
?
3
BS
S M
Operator Type Check - $in
Roadmap
E-S-R Overview
Focus:
• Equality
• Sort
• Range
E-S-R Considerations
Operator Type Checks
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})Recommended index:
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
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
Ace
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1
Ace
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1
Ace
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
5,000 9,0019,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1 2
Ace
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
5,000 9,0019,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1 2
Ace
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
9,0019,000
… …
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1 2 5,000
Ace
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
9,0019,000
…
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1 5,0002
…
Ace
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
9,001
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1 5,0002 9,000
… …
Ace
db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
9,001
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1 5,0002 9,000
… …
Ace
db.games.createIndex({gamertag:1, score:1, date:1})
✓
Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1 5,000 9,0012 9,000
… …
Ace
db.games.createIndex({gamertag:1, score:1, date:1})
✓
Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"score" : [
"[MinKey, MaxKey]"
],
"date" : [
"[2019.0, inf.0]"
]
}
{1} {2}
1 5,000 9,0012 9,000
… …
Ace
db.games.createIndex({gamertag:1, score:1, date:1})
✓ ✓
Recommended index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
2001 2000 2015 2019 2019
gamertag
score
date
{} {} {}
"executionStats" : {
"nReturned" : 2,
"executionTimeMillis" : 23,
"totalKeysExamined" : 9001,
"totalDocsExamined" : 2,
{1} {2}
1 5,000 9,0012 9,000
… …
Ace
db.games.createIndex({gamertag:1, score:1, date:1})
✓ ✓
Recommended index:
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
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
db.games.createIndex({gamertag:1, date:1})ANTI-pattern index:
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
db.games.createIndex({gamertag:1, date:1})ANTI-pattern index:
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]"
]
}
ANTI-pattern index:
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
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}
db.games.createIndex({gamertag:1, date:1})ANTI-pattern index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
… …
2000 2001 2015 2019 2019
{score:2} {score:1} {score:5000} {score:9001} {score:9000}
gamertag
date
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}Ace
db.games.createIndex({gamertag:1, date:1})ANTI-pattern index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
… …
2000 2001 2015 2019 2019
{score:2} {score:1} {score:5000} {score:9001} {score:9000}
gamertag
date
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}Ace
db.games.createIndex({gamertag:1, date:1})
✓
ANTI-pattern index:
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
… …
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,
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}Ace
db.games.createIndex({gamertag:1, date:1})
✓ ✓
ANTI-pattern index:
Exceptions
……… …
BS
S
R
E
R
E
Index: {gamertag:1, date:1}
Index: {gamertag:1, score:1, date:1}
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
Tips and Tricks++ for Indexing MongoDB
Ronan Bohan https://www.surveymonkey.com/r/KF8KX7B
Thank You!
And Thank You
from me too!
Appendix
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
.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"
})
{} {} {} {}
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
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})
Ace
Consecutive Index Keys
Mario Halo
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})
2016
Ace
Consecutive Index Keys
Mario Halo
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})
2016
Ace
Consecutive Index Keys
Mario Halo 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})
2016 2017
Ace
Consecutive Index Keys
Mario Halo 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})
2016 2017
Ace
✓
Consecutive Index Keys
Mario Halo Mario Halo
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})
2016 2017 2018
Ace
✓
Consecutive Index Keys
Mario Halo Mario Halo
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})
2016 2017 2018
Ace
✓
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
Consecutive Index Keys
Mario Halo Mario Halo
.find({
gamertag:"Ace",
game: "Halo"
})
{} {} {} {}
db.games.createIndex({gamertag:1, date:1, game:1})
2016 2017 2018 2019
Ace
✓
Consecutive Index Keys
Mario Halo Mario Halo
.find({
gamertag:"Ace",
game: "Halo"
})
{} {}
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[MinKey, MaxKey]"
],
"game" : [
"["Halo", "Halo"]"
]
}
{} {}
db.games.createIndex({gamertag:1, date:1, game:1})
2016 2017 2018 2019
Ace
✓ ✓
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
Consecutive Index Keys
.find({
gamertag:"Ace",
game: "Halo"
})
{} {} {} {}
"date" : [
"[MinKey, MaxKey]"
],
HaloMario Halo
2016 2017
Mario
2018 2019 "game" : [
"["Halo", "Halo"]"
]
}
db.games.createIndex({gamertag:1, game:1})
Ace
✓
2016 2017Mario2018 2019Halo
Consecutive Index Keys
.find({
gamertag:"Ace",
game: "Halo"
})
],
"date" : [
"[MinKey, MaxKey]"
]
}
}
{}{} {}{}
db.games.createIndex({gamertag:1, game:1, date:1})
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"game" : [
"["Halo", "Halo"]"
]
Ace
✓✓
R
E
E E
E
E
E
Consecutive Index Keys
R
Look familiar? This is equality after range!

Mais conteúdo relacionado

Mais procurados

Gareth hayes. non alphanumeric javascript-php and shared fuzzing
Gareth hayes. non alphanumeric javascript-php and shared fuzzingGareth hayes. non alphanumeric javascript-php and shared fuzzing
Gareth hayes. non alphanumeric javascript-php and shared fuzzing
Yury Chemerkin
 
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
MongoSF
 
Implementation Specifications
Implementation SpecificationsImplementation Specifications
Implementation Specifications
Unmon Mukherjee
 

Mais procurados (20)

Mapping Flatland: Using MongoDB for an MMO Crossword Game (GDC Online 2011)
Mapping Flatland: Using MongoDB for an MMO Crossword Game (GDC Online 2011)Mapping Flatland: Using MongoDB for an MMO Crossword Game (GDC Online 2011)
Mapping Flatland: Using MongoDB for an MMO Crossword Game (GDC Online 2011)
 
Gareth hayes. non alphanumeric javascript-php and shared fuzzing
Gareth hayes. non alphanumeric javascript-php and shared fuzzingGareth hayes. non alphanumeric javascript-php and shared fuzzing
Gareth hayes. non alphanumeric javascript-php and shared fuzzing
 
MongoDB San Francisco 2013: Hash-based Sharding in MongoDB 2.4 presented by B...
MongoDB San Francisco 2013: Hash-based Sharding in MongoDB 2.4 presented by B...MongoDB San Francisco 2013: Hash-based Sharding in MongoDB 2.4 presented by B...
MongoDB San Francisco 2013: Hash-based Sharding in MongoDB 2.4 presented by B...
 
MongoDB
MongoDB MongoDB
MongoDB
 
Mongo db mug_2012-02-07
Mongo db mug_2012-02-07Mongo db mug_2012-02-07
Mongo db mug_2012-02-07
 
Modern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapModern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter Bootstrap
 
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
 
Implementation Specifications
Implementation SpecificationsImplementation Specifications
Implementation Specifications
 
SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling
SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling
SenchaCon 2016: Handle Real-World Data with Confidence - Fredric Berling
 
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
 
Every Click Counts (But All the Money Goes to Me)
Every Click Counts (But All the Money Goes to Me)Every Click Counts (But All the Money Goes to Me)
Every Click Counts (But All the Money Goes to Me)
 
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.9 book - Part 53 of 210
 
JavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScriptJavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScript
 
The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31The Ring programming language version 1.4.1 book - Part 13 of 31
The Ring programming language version 1.4.1 book - Part 13 of 31
 
The Ring programming language version 1.3 book - Part 34 of 88
The Ring programming language version 1.3 book - Part 34 of 88The Ring programming language version 1.3 book - Part 34 of 88
The Ring programming language version 1.3 book - Part 34 of 88
 
Powering Systems of Engagement
Powering Systems of EngagementPowering Systems of Engagement
Powering Systems of Engagement
 
Advanced MongoDB #1
Advanced MongoDB #1Advanced MongoDB #1
Advanced MongoDB #1
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
 
ETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDBETL for Pros: Getting Data Into MongoDB
ETL for Pros: Getting Data Into MongoDB
 
The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185
 

Semelhante a MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB

Tips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query PitfallsTips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 

Semelhante a MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB (20)

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 .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
 
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing Mo...
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing Mo...MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing Mo...
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing Mo...
 
MongoDB .local Houston 2019:Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local Houston 2019:Tips and Tricks++ for Querying and Indexing MongoDBMongoDB .local Houston 2019:Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB .local Houston 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
 
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query PitfallsMongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
 
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 Sydney 2019: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB.local Sydney 2019: Tips and Tricks for Avoiding Common Query PitfallsMongoDB.local Sydney 2019: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB.local Sydney 2019: Tips and Tricks for Avoiding Common Query Pitfalls
 
Tips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query PitfallsTips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query Pitfalls
 
Tips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query PitfallsTips and Tricks for Avoiding Common Query Pitfalls
Tips and Tricks for Avoiding Common Query Pitfalls
 
MongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB World 2018: Tips and Tricks for Avoiding Common Query PitfallsMongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB World 2018: Tips and 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 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
 
Liferay Search: Best Practices to Dramatically Improve Relevance - Liferay Sy...
Liferay Search: Best Practices to Dramatically Improve Relevance - Liferay Sy...Liferay Search: Best Practices to Dramatically Improve Relevance - Liferay Sy...
Liferay Search: Best Practices to Dramatically Improve Relevance - Liferay Sy...
 
Casting for not so strange actors
Casting for not so strange actorsCasting for not so strange actors
Casting for not so strange actors
 
NUS iOS Swift Talk
NUS iOS Swift TalkNUS iOS Swift Talk
NUS iOS Swift Talk
 
Graph abstraction
Graph abstractionGraph abstraction
Graph abstraction
 

Mais de MongoDB

Mais de 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
 

Último

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Último (20)

The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
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
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
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
 
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
 
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
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 

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

  • 1.
  • 2. Tips and Tricks++ for Indexing MongoDB Ronán Bohan Principal Solutions Architect, EMEA v 20190922
  • 3. Introductions { name : “Ronán Bohan”, role : “Principal Solutions Architect” }
  • 4. Introductions I’ve identified some slow queries. What indexes do I create?
  • 5. Introductions For that we’re going to look at compound indexes and the “E-S-R” rule
  • 6. Roadmap E-S-R Overview Deep dive: • Equality • Sort • Range E-S-R Considerations Operator Type Checks Exceptions?
  • 8. E-S-R The ordering of index keys in a compound index is critically important.
  • 9. E-S-R The ordering of index keys in a compound index is critically important. Sure, but does it really matter?
  • 10. 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
  • 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. Equality Fields Definitions An exact match on a single value. For example: • {x:123} • {x:{$eq:123}} • {"x.y":123} Bounds: "[123.0, 123.0]" Sort Range Predicates
  • 13. Definitions Sort The (entire) requested sort. .sort({a:1}) .sort({a:1, b:-1}) An exact match on a single value. For example: • {x:123} • {x:{$eq:123}} • {"x.y":123} Bounds: "[123.0, 123.0]" Bounds: "[MinKey, MaxKey]" Range PredicatesEquality Fields "[MinKey, MaxKey]", "[MinKey, MaxKey]"
  • 14. Definitions Sort Range Predicates Any predicates that are not exact matches. Some operators include: • {z:{$gt:9000}} • {foo:{$lte:1000}} The (entire) requested sort. .sort({a:1}) .sort({a:1, b:-1}) An exact match on a single value. For example: • {x:123} • {x:{$eq:123}} • {"x.y":123} Bounds: "[123.0, 123.0]" Bounds: "[MinKey, MaxKey]", "[MinKey, MaxKey]" Bounds: "(9000.0, inf.0]" "[-inf.0, 1000]" Equality Fields
  • 15. Roadmap E-S-R Overview Deep dive: • Equality • Sort • Range E-S-R Considerations Operator Type Checks 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. 99,999 {gamertag: "Bob", score: 15,000}{gamertag: "Ace", score: 100} db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {}{} 100 15,000 50,000 Ace Bob Bob Ace {gamertag: "Ace", score: 99,999} {gamertag: "Bob", score: 50,000} Equality db.games.createIndex({score:1, gamertag:1}) gamertag score ANTI-pattern index:
  • 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}) gamertag score ANTI-pattern index:
  • 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"]" ] } db.games.createIndex({score:1, gamertag:1}) gamertag score ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 32. 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) Equality db.games.createIndex({gamertag:1, score:1})Recommended index:
  • 33. Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) 100 99,999 15,000 50,000 {} {} {} {} Equality db.games.createIndex({gamertag:1, score:1}) gamertag score Recommended index:
  • 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}) gamertag score Recommended index:
  • 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}) score Recommended index:
  • 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})Recommended index:
  • 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})Recommended index:
  • 38. 100 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 Ace db.games.createIndex({gamertag:1, score:1})Recommended index:
  • 39. 100 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 Ace ✓ db.games.createIndex({gamertag:1, score:1})Recommended index:
  • 40. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Equality before Range Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
  • 41. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Equality before Range Index: {gamertag:1, score:1}Index: {score:1, gamertag:1} Hey! Don’t forget about your demo!!
  • 42. Roadmap E-S-R Overview Deep dive: • Equality • Sort • Range E-S-R Considerations Operator Type Checks Exceptions?
  • 43. Sort fields are placed next Placing sort predicates after sequential equality keys allows the index to: - Provide a non-blocking sort. - Minimize the amount of scanning required. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort
  • 44. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 45. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {} {} {} {} db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 46. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {} {} {} {} db.games.createIndex({score:1, gamertag:1})ANTI-pattern index: "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score
  • 47. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {} {} {} {} db.games.createIndex({score:1, gamertag:1})ANTI-pattern index: "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score
  • 48. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.createIndex({score:1, gamertag:1})ANTI-pattern index: "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score
  • 49. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Acegamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 50. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Acegamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 51. db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) Sort 100 15,000 50,000 99,999 Ace Bob Bob Acegamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 52. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} ✓ db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 53. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} ✓ db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 54. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} ✓ db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 55. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} ✓ db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 56. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} ✓ db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 57. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} ✓ db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 58. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]" ] } {1} {} {} {2} ✓✓ db.games.createIndex({score:1, gamertag:1})ANTI-pattern index:
  • 59. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
  • 60. Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) db.games.createIndex({gamertag:1, score:1})Recommended index:
  • 61. Sort Ace Bob Bob Ace 100 99,999 15,000 50,000 {1} {2} {} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) db.games.createIndex({gamertag:1, score:1}) gamertag score Recommended index:
  • 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})Recommended index:
  • 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})Recommended index:
  • 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})Recommended index:
  • 65. Sort 100 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]" ] } Ace db.games.createIndex({gamertag:1, score:1})Recommended index:
  • 66. Sort 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]" ] } 100 Ace ✓ db.games.createIndex({gamertag:1, score:1})Recommended index:
  • 67. Sort Bob 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ] } 100 99,999 Ace ✓ ✓ db.games.createIndex({gamertag:1, score:1})Recommended index:
  • 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 Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
  • 69. Roadmap E-S-R Overview Deep dive: • Equality • Sort • Range E-S-R Considerations Operator Type Checks 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}} ) Range Haven’t we seen this before?
  • 72. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Range after Equality Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
  • 73. db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Range But should range come after sort too? Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
  • 74. R E R E Range db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) But should range come after sort too? Index: {gamertag:1, score:1}Index: {score:1, gamertag:1}
  • 75. R E R E Range db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) But should range come after sort too? Index: {gamertag:1, score:1}Index: {score:1, gamertag:1} db.games.createIndex({…, score:1, gamertag:1})ANTI-pattern index:
  • 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})ANTI-pattern index:
  • 77. 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})ANTI-pattern index:
  • 78. 100 15,000 50,000 99,999 Ace Bob Cal Ace * db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score db.games.createIndex({…, score:1, gamertag:1})ANTI-pattern index:
  • 79. 100 15,000 50,000 99,999 Ace Bob Cal Ace * db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {} {} {}{1}{2} {3} gamertag score db.games.createIndex({…, score:1, gamertag:1})ANTI-pattern index:
  • 80. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 81. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 82. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 83. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 84. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 85. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 86. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 87. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 88. 100 15,000 50,000 99,999 Ace Bob Cal 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})ANTI-pattern index:
  • 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. db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 92. 100 15,000 50,000 99,999 Ace Bob Cal Ace * db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 93. db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range * Ace Bob Cal Ace 100 15,000 50,00099,999 {} {1} {2} {3} db.games.createIndex({…, gamertag:1, score:1}) score gamertag Recommended index:
  • 94. * 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 95. * 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 96. 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} * db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 97. 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} * db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 98. 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} * ✓ db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 99. 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} * ✓ db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 100. 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} * ✓ ✓ db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 101. 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} * ✓ ✓ db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 102. 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} * ✓ ✓ ✓ db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 103. 100 15,000 50,00099,999 Ace Bob Cal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } {2} * db.games.createIndex({…, gamertag:1, score:1})Recommended index:
  • 104. BS R S R S db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range after Sort Index: {…, gamertag:1, score:1} Index: {…, score:1, gamertag:1}
  • 105. Roadmap E-S-R Overview Deep dive: • Equality • Sort • Range E-S-R Considerations Operator Type Checks 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 zebra
  • 122. Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry zebra
  • 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! cArrycarry 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
  • 130. Operator Type Check - $in $in filters: E, S, or R? • {field:{$in:[1,3]}} … it depends with respect to query shape and key ordering Alone: a series of Equality matches Combined: possibly a Range
  • 131. Operator Type Check - $in .find({field1:{$in:[1,3]}})
  • 132. Operator Type Check - $in .find({field1:{$in:[1,3]}}) db.coll.createIndex({field1:1, field2:1})
  • 133. Operator Type Check - $in .find({field1:{$in:[1,3]}}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } 2 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? 1 3
  • 134. Operator Type Check - $in .find({field1:{$in:[1,3]}}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } 2 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? 31
  • 135. Operator Type Check - $in .find({field1:{$in:[1,3]}}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } 2 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? 31
  • 136. Operator Type Check - $in .find({field1:{$in:[1,3]}}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } 2 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? 31
  • 137. Operator Type Check - $in .find({field1:{$in:[1,3]}}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } 2 C G B F A D db.coll.createIndex({field1:1, field2:1}) 1 3 ?
  • 138. Operator Type Check - $in .find({field1:{$in:[1,3]}}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 1 2 3 C G B F A D db.coll.createIndex({field1:1, field2:1})
  • 139. Operator Type Check - $in .find({field1:{$in:[1,3]}}) .sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ] } ? 2 C G B F A D db.coll.createIndex({field1:1, field2:1}) 1 3
  • 140. Operator Type Check - $in .find({field1:{$in:[1,3]}}) .sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "field2" : [ "[MinKey, MaxKey]" ] } ? 2 C G B F A D 1 3 db.coll.createIndex({field1:1, field2:1})
  • 141. Operator Type Check - $in .find({field1:{$in:[1,3]}}) .sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "field2" : [ "[MinKey, MaxKey]" ] } ? 2 C G B F A D 1 3 db.coll.createIndex({field1:1, field2:1})
  • 142. Operator Type Check - $in .find({field1:{$in:[1,3]}}) .sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "field2" : [ "[MinKey, MaxKey]" ] } ? 2 C G B F A D 1 3 db.coll.createIndex({field1:1, field2:1})
  • 143. Operator Type Check - $in .find({field1:{$in:[1,3]}}) .sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "field2" : [ "[MinKey, MaxKey]" ] } ? 2 C G B F A D BS 1 3 db.coll.createIndex({field1:1, field2:1})
  • 144. Operator Type Check - $in .find({field1:{$in:[1,3]}}) .sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", "[3.0, 3.0]" ], "field2" : [ "[MinKey, MaxKey]" ] } ? 1 2 3 C G B F A D BS db.coll.createIndex({field1:1, field2:1})
  • 145. Operator Type Check - $in db.coll.createIndex({field1:1, field2:1}) .find({field1:{$in:[1,3]}}).sort({field2:1})
  • 146. .find({field1:{$in:[1,3]}}).sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } Operator Type Check - $in 2 3 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? 1
  • 147. .find({field1:{$in:[1,3]}}).sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } Operator Type Check - $in 2 3 C G B F A D db.coll.createIndex({field1:1, field2:1}) 1 ?
  • 148. .find({field1:{$in:[1,3]}}).sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } Operator Type Check - $in 2 3 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? 1
  • 149. .find({field1:{$in:[1,3]}}).sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } Operator Type Check - $in 2 3 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? 1
  • 150. .find({field1:{$in:[1,3]}}).sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field1" : [ "[3.0, 3.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } Operator Type Check - $in 2 3 C G B F A D ? 1 2 3 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? 1
  • 151. .find({field1:{$in:[1,3]}}).sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field1" : [ "[3.0, 3.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } Operator Type Check - $in 1 2 3 C G B F A D 1 2 3 C G B F A D db.coll.createIndex({field1:1, field2:1}) ? ?
  • 152. .find({field1:{$in:[1,3]}}).sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field1" : [ "[3.0, 3.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } Operator Type Check - $in 2 3 C G B F A D 1 2 C G B F A D db.coll.createIndex({field1:1, field2:1}) 3 ? 1 ?
  • 153. .find({field1:{$in:[1,3]}}).sort({field2:1}) "indexBounds" : { "field1" : [ "[1.0, 1.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } "indexBounds" : { "field1" : [ "[3.0, 3.0]", ], "field2" : [ "[MinKey, MaxKey]" ] } Operator Type Check - $in 2 3 C G B F A D 1 2 C G B F A D {2} {4} {1} {3} Sort Merge db.coll.createIndex({field1:1, field2:1}) ? 1 ? 3
  • 154. BS S M Operator Type Check - $in
  • 155. Roadmap E-S-R Overview Focus: • Equality • Sort • Range E-S-R Considerations Operator Type Checks Exceptions?
  • 156. 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})
  • 157. 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})Recommended index:
  • 158. 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 {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 159. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} Ace db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 160. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 Ace db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 161. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 Ace db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 162. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 5,000 9,0019,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 2 Ace db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 163. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 5,000 9,0019,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 2 Ace db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 164. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 9,0019,000 … … 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 2 5,000 Ace db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 165. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 9,0019,000 … 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 5,0002 … Ace db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 166. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 9,001 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 5,0002 9,000 … … Ace db.games.createIndex({gamertag:1, score:1, date:1})Recommended index:
  • 167. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 9,001 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 5,0002 9,000 … … Ace db.games.createIndex({gamertag:1, score:1, date:1}) ✓ Recommended index:
  • 168. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 5,000 9,0012 9,000 … … Ace db.games.createIndex({gamertag:1, score:1, date:1}) ✓ Recommended index:
  • 169. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 2001 2000 2015 2019 2019 gamertag score date {} {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "[MinKey, MaxKey]" ], "date" : [ "[2019.0, inf.0]" ] } {1} {2} 1 5,000 9,0012 9,000 … … Ace db.games.createIndex({gamertag:1, score:1, date:1}) ✓ ✓ Recommended index:
  • 170. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) 2001 2000 2015 2019 2019 gamertag score date {} {} {} "executionStats" : { "nReturned" : 2, "executionTimeMillis" : 23, "totalKeysExamined" : 9001, "totalDocsExamined" : 2, {1} {2} 1 5,000 9,0012 9,000 … … Ace db.games.createIndex({gamertag:1, score:1, date:1}) ✓ ✓ Recommended index:
  • 172. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) Ace 1 5,000 9,0012 9,000 … … 2001 2000 2015 2019 2019 db.games.createIndex({gamertag:1, date:1})ANTI-pattern index:
  • 173. 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 db.games.createIndex({gamertag:1, date:1})ANTI-pattern index:
  • 174. 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]" ] } ANTI-pattern index:
  • 175. 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 "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] } db.games.createIndex({gamertag:1, date:1})ANTI-pattern index:
  • 176. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) … … 2000 2001 2015 2019 2019 {score:2} {score:1} {score:5000} {score:9001} {score:9000} gamertag date "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }Ace db.games.createIndex({gamertag:1, date:1})ANTI-pattern index:
  • 177. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) … … 2000 2001 2015 2019 2019 {score:2} {score:1} {score:5000} {score:9001} {score:9000} gamertag date "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }Ace db.games.createIndex({gamertag:1, date:1}) ✓ ANTI-pattern index:
  • 178. Exceptionsdb.games .find({gamertag:"Ace", date:{$gte:2019}}) .sort({score:1}) … … 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, "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] }Ace db.games.createIndex({gamertag:1, date:1}) ✓ ✓ ANTI-pattern index:
  • 179. Exceptions ……… … BS S R E R E Index: {gamertag:1, date:1} Index: {gamertag:1, score:1, date:1}
  • 181. 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
  • 182. Tips and Tricks++ for Indexing MongoDB Ronan Bohan https://www.surveymonkey.com/r/KF8KX7B
  • 183. Thank You! And Thank You from me too!
  • 184.
  • 185.
  • 187. 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" })
  • 189. Consecutive Index Keys .find({ gamertag:"Ace", game: "Halo" }) db.games.createIndex({gamertag:1, date:1, game:1})
  • 190. 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})
  • 191. 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})
  • 192. 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})
  • 193. 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})
  • 194. Consecutive Index Keys 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}) Ace
  • 195. Consecutive Index Keys Mario Halo 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}) 2016 Ace
  • 196. Consecutive Index Keys Mario Halo 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}) 2016 Ace
  • 197. Consecutive Index Keys Mario Halo 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}) 2016 2017 Ace
  • 198. Consecutive Index Keys Mario Halo 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}) 2016 2017 Ace ✓
  • 199. Consecutive Index Keys Mario Halo Mario Halo 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}) 2016 2017 2018 Ace ✓
  • 200. Consecutive Index Keys Mario Halo Mario Halo 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}) 2016 2017 2018 Ace ✓
  • 201. "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } Consecutive Index Keys Mario Halo Mario Halo .find({ gamertag:"Ace", game: "Halo" }) {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1}) 2016 2017 2018 2019 Ace ✓
  • 202. Consecutive Index Keys Mario Halo Mario Halo .find({ gamertag:"Ace", game: "Halo" }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1}) 2016 2017 2018 2019 Ace ✓ ✓
  • 203. "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], Consecutive Index Keys .find({ gamertag:"Ace", game: "Halo" }) {} {} {} {} "date" : [ "[MinKey, MaxKey]" ], HaloMario Halo 2016 2017 Mario 2018 2019 "game" : [ "["Halo", "Halo"]" ] } db.games.createIndex({gamertag:1, game:1}) Ace ✓
  • 204. 2016 2017Mario2018 2019Halo Consecutive Index Keys .find({ gamertag:"Ace", game: "Halo" }) ], "date" : [ "[MinKey, MaxKey]" ] } } {}{} {}{} db.games.createIndex({gamertag:1, game:1, date:1}) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "game" : [ "["Halo", "Halo"]" ] Ace ✓✓
  • 205. R E E E E E E Consecutive Index Keys R Look familiar? This is equality after range!