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

MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexing MongoDB

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