SlideShare a Scribd company logo
WHEN
WHERE
Tips and Tricks++ for Querying and
Indexing MongoDB
Dr. Christian Kurze, Principal Solutions Architect
22 October 2019, 03:00 – 3:45PM
Room 1
#MDBLocal
#MDBLocal
Is there anything new
about indexes
in MongoDB 4.2
that I should be aware of?
#MDBLocal
{
"_id" : ObjectId("5c1d358bf383fbee028aea0b"),
"product_name" : "Blaster Gauntlet",
"product_attributes" : {
"elements" : [ "Fire" , "Water" ],
"price" : 250
...
}
},
{
"_id" : ObjectId("5c1d358bf383fbee028aea0c"),
"product_name" : "Super Suit",
"product_attributes" : {
"superFlight" : true,
"resistance" : [ "Bludgeoning", "Piercing",
"Slashing" ]
...
},
}
Wildcard Indexes
Allow more natural data modeling,
avoids pre-defining indexes for
every access pattern
Polymorphic document structures:
Product catalogs, CMS
Ad-hoc queries & data exploration
Define a filter that indexes all
matching fields, sub-documents,
and arrays
Sparse index, omit specific fields
Covered queries & collations
Strongly consistent: updated atomically
with base data
Index all sub-documents &
arrays under Product Attributes
#MDBLocal
I identified slow queries.
What index do I make?
#MDBLocal
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
#MDBLocal
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"
#MDBLocal
E-S-R
The ordering of index keys in a compound index is critically important.
#MDBLocal
E-S-R
The ordering of index keys in a compound index is critically important.
Does it really matter?
#MDBLocal
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
#MDBLocal
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?
#MDBLocal
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]"
#MDBLocal
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]"
#MDBLocal
Definitions
Equality Fields Sort Range Predicates
Any predicates that are not
exact matches. Some
operators include:
• {z:{$gt:9000}}
• {z:{$lte:1000}}
Bounds:
"[9000.0, inf.0]",
The (entire) requested sort.
.sort({a:1, b:-1})
Bounds:
"[MinKey, MaxKey]",
"[MinKey, MaxKey]"
An exact match on a single
value. For example:
• {x:123}
• {x:{$eq:123}}
• {"x.y":123}
Bounds:
"[123.0, 123.0]"
#MDBLocal
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
#MDBLocal
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.
#MDBLocal
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?
#MDBLocal
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}} )
#MDBLocal
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
#MDBLocal
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}
#MDBLocal
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
db.games.createIndex({score:1, gamertag:1})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
100 15,000 50,000 99,999
Ace Bob Bob Ace
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
{} {} {} {}
Equality
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Equality before Range
#MDBLocal
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
#MDBLocal
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
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
Sort
100 15,000 50,000 99,999
Ace Bob Bob Ace
{1} {} {} {2}
db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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
#MDBLocal
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
#MDBLocal
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
#MDBLocal
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Range after Equality
#MDBLocal
db.games.find( {gamertag: "Ace", score: {$gt: 9000}} )
R
E R
E
Range after Equality
Should range come after sort
too?
#MDBLocal
R
E R
E
Range after Equality
Should range come after sort
too?
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
#MDBLocal
R
E R
E
Range
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
{2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
Blocking SortBlocking
Sort
BS
#MDBLocal
{2}{3}{1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
BS
#MDBLocal
100 15,000 50,000 99,999
Ace Bob Cali Ace
*
{} {2} {3} {1}
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
#MDBLocal
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range
*
Ace Bob Cali Ace
100 15,000 50,00099,999
{} {1} {2} {3}
db.games.createIndex({ …, gamertag:1, score:1})
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
*
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}
#MDBLocal
BS
R S
R
S
db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
Range after Sort
#MDBLocal
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
#MDBLocal
Operator Type Check
Some operators are simple
$eq: Equality
$gte: Range
Others are trickier
#MDBLocal
Operator Type Check - Inequality
Inequality Operators: E, S, or R?
• $ne:123
• $nin:[1,2]
Range!
#MDBLocal
Operator Type Check - Inequality
Inequality Operators: E, S, or R?
• $ne:123
• $nin:[1,2]
Range!
How do you know?
#MDBLocal
Operator Type Check - Inequality
Inequality Operators: E, S, or R?
• $ne:123
• $nin:[1,2]
Range!
"indexBounds" : {
"x" : [
"[MinKey, 123.0)",
"(123.0, MaxKey]"
]
}
#MDBLocal
Operator Type Check - Inequality
Range!
"indexBounds" : {
"x" : [
"[MinKey, 123.0)",
"(123.0, MaxKey]"
]
}
50 123 999
#MDBLocal
Operator Type Check - Inequality
Range!
"indexBounds" : {
"x" : [
"[MinKey, 123.0)",
"(123.0, MaxKey]"
]
}
50 123 999
#MDBLocal
Operator Type Check - Inequality
Range!
"indexBounds" : {
"x" : [
"[MinKey, 123.0)",
"(123.0, MaxKey]"
]
}
50 123 999
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
planecar racecar
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
planecar racecar
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
planecar racecar
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
p???ecar racecar
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
p???ecar racecar
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry Carpool
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry Carpool
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
raincarry Carpool
#MDBLocal
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?
#MDBLocal
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?
#MDBLocal
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?
#MDBLocal
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?
#MDBLocal
Operator Type Check - Regex
Regex Operators: E, S, or R?
• {str:/car/}
• {str:/^car/i}
Range!
cArrycarry Carpool
#MDBLocal
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
#MDBLocal
Operator Type Check - $in
.find({field:{$in:[1,3]}})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
BS
S M
Operator Type Check - $in
#MDBLocal
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
#MDBLocal
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”
})
#MDBLocal
Consecutive Index Keys
.find({
gamertag:"Ace",
game: "Halo”
})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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, date:1, game:1})
#MDBLocal
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, date:1, game:1})
#MDBLocal
R
E
E E
E
E
E
Consecutive Index Keys
R
Look familiar? This is equality after range!
#MDBLocal
Roadmap
E-S-R Overview
Guidelines:
• Eà R
• Eà S
• Sà R
E-S-R Considerations
Operator Type Checks
Consecutive Index Keys
Exceptions?
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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,
{1} {2}
db.games.createIndex({gamertag:1, score:1, date:1})
#MDBLocal
Exceptionsdb.games
.find({gamertag:"Ace", date:{$gte:2019}})
.sort({score:1})
Ace
1 5,000 9,0012 9,000
… …
2001 2000 2015 2019 2019
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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})
#MDBLocal
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,
"indexBounds" : {
"gamertag" : [
"["Ace", "Ace"]"
],
"date" : [
"[2019.0, inf.0]"
]
}
db.games.createIndex({gamertag:1, date:1})
#MDBLocal
Exceptions
……… …
BS
S
R
E
R
E
Summary
#MDBLocal
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:
• Indexing is important from day one,
things get slow as the data grows
• 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
M201: Performance in MongoDB
university.mongodb.com
THANK YOU
MongoDB .local Munich 2019: Tips and Tricks++ for Querying and Indexing MongoDB

More Related Content

What's hot (20)

PDF
MongoDB World 2019: Using Client Side Encryption in MongoDB 4.2 Link
MongoDB
 
PPTX
Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
MongoDB
 
PDF
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
GeeksLab Odessa
 
PDF
MongoDB .local London 2019: Using Client Side Encryption in MongoDB 4.2
Lisa Roth, PMP
 
PPTX
Webinar: General Technical Overview of MongoDB for Dev Teams
MongoDB
 
PPTX
Powering Systems of Engagement
MongoDB
 
PDF
MongoDB Performance Tuning
Puneet Behl
 
PPTX
MongoDB 3.2 - Analytics
Massimo Brignoli
 
PDF
MongoDB With Style
Gabriele Lana
 
PPTX
MongoDB - Back to Basics - La tua prima Applicazione
Massimo Brignoli
 
PDF
MongoD Essentials
zahid-mian
 
KEY
Geospatial Indexing and Querying with MongoDB
Grant Goodale
 
KEY
Schema design
christkv
 
PDF
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB
 
PPT
Every Click Counts (But All the Money Goes to Me)
Avast
 
PDF
Webinar: Building Your First App with MongoDB and Java
MongoDB
 
KEY
How Signpost uses MongoDB for Tracking and Analytics
mattinsler
 
PPTX
Back to Basics: My First MongoDB Application
MongoDB
 
PPTX
MongoDB Live Hacking
Tobias Trelle
 
PPT
Top Ten Web Defenses - DefCamp 2012
DefCamp
 
MongoDB World 2019: Using Client Side Encryption in MongoDB 4.2 Link
MongoDB
 
Webinarserie: Einführung in MongoDB: “Back to Basics” - Teil 3 - Interaktion ...
MongoDB
 
Java/Scala Lab: Борис Трофимов - Обжигающая Big Data.
GeeksLab Odessa
 
MongoDB .local London 2019: Using Client Side Encryption in MongoDB 4.2
Lisa Roth, PMP
 
Webinar: General Technical Overview of MongoDB for Dev Teams
MongoDB
 
Powering Systems of Engagement
MongoDB
 
MongoDB Performance Tuning
Puneet Behl
 
MongoDB 3.2 - Analytics
Massimo Brignoli
 
MongoDB With Style
Gabriele Lana
 
MongoDB - Back to Basics - La tua prima Applicazione
Massimo Brignoli
 
MongoD Essentials
zahid-mian
 
Geospatial Indexing and Querying with MongoDB
Grant Goodale
 
Schema design
christkv
 
MongoDB Europe 2016 - Debugging MongoDB Performance
MongoDB
 
Every Click Counts (But All the Money Goes to Me)
Avast
 
Webinar: Building Your First App with MongoDB and Java
MongoDB
 
How Signpost uses MongoDB for Tracking and Analytics
mattinsler
 
Back to Basics: My First MongoDB Application
MongoDB
 
MongoDB Live Hacking
Tobias Trelle
 
Top Ten Web Defenses - DefCamp 2012
DefCamp
 

Similar to MongoDB .local Munich 2019: Tips and Tricks++ for Querying and Indexing MongoDB (20)

PDF
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
Lisa Roth, PMP
 
PPTX
Avoid Query Pitfalls
Norberto Leite
 
PPTX
MongoDB.local Dallas 2019: Tips & Tricks for Avoiding Common Query Pitfalls
MongoDB
 
PDF
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
PDF
Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
PPTX
MongoDB.local Sydney 2019: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
PDF
Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
PDF
MongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
PDF
MongoDB World 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB
 
PDF
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing Mo...
MongoDB
 
PDF
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB
 
PPTX
Tips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
MongoDB
 
PPTX
MongoDB.local Seattle 2019: Tips & Tricks for Avoiding Common Query Pitfalls
MongoDB
 
PDF
MongoDB .local Houston 2019:Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB
 
PDF
MongoDB
Hemant Kumar Tiwary
 
PDF
JavaScript Code Formatting With Prettier by Christopher Chedeau
React London 2017
 
PPTX
Mongo db mug_2012-02-07
Will Button
 
PDF
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
MongoSF
 
PPTX
MongoDB World 2018: Keynote
MongoDB
 
PDF
Indexing
Mike Dirolf
 
MongoDB .local London 2019: Tips and Tricks++ for Querying and Indexing MongoDB
Lisa Roth, PMP
 
Avoid Query Pitfalls
Norberto Leite
 
MongoDB.local Dallas 2019: Tips & Tricks for Avoiding Common Query Pitfalls
MongoDB
 
MongoDB.local Austin 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
MongoDB.local Sydney 2019: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
MongoDB World 2018: Tips and Tricks for Avoiding Common Query Pitfalls
MongoDB
 
MongoDB World 2019: Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB
 
MongoDB .local Bengaluru 2019: Tips and Tricks++ for Querying and Indexing Mo...
MongoDB
 
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB
 
Tips and Tricks for Avoiding Common Query Pitfalls Christian Kurze
MongoDB
 
MongoDB.local Seattle 2019: Tips & Tricks for Avoiding Common Query Pitfalls
MongoDB
 
MongoDB .local Houston 2019:Tips and Tricks++ for Querying and Indexing MongoDB
MongoDB
 
JavaScript Code Formatting With Prettier by Christopher Chedeau
React London 2017
 
Mongo db mug_2012-02-07
Will Button
 
Map/reduce, geospatial indexing, and other cool features (Kristina Chodorow)
MongoSF
 
MongoDB World 2018: Keynote
MongoDB
 
Indexing
Mike Dirolf
 
Ad

More from MongoDB (20)

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

Recently uploaded (20)

PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
PPTX
Designing Production-Ready AI Agents
Kunal Rai
 
PDF
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
PDF
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
PDF
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
PDF
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PDF
Using FME to Develop Self-Service CAD Applications for a Major UK Police Force
Safe Software
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
DOCX
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
Designing Production-Ready AI Agents
Kunal Rai
 
Transforming Utility Networks: Large-scale Data Migrations with FME
Safe Software
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 
Mastering Financial Management in Direct Selling
Epixel MLM Software
 
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
Go Concurrency Real-World Patterns, Pitfalls, and Playground Battles.pdf
Emily Achieng
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Using FME to Develop Self-Service CAD Applications for a Major UK Police Force
Safe Software
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
“NPU IP Hardware Shaped Through Software and Use-case Analysis,” a Presentati...
Edge AI and Vision Alliance
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
Python coding for beginners !! Start now!#
Rajni Bhardwaj Grover
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 

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

  • 1. WHEN WHERE Tips and Tricks++ for Querying and Indexing MongoDB Dr. Christian Kurze, Principal Solutions Architect 22 October 2019, 03:00 – 3:45PM Room 1
  • 3. #MDBLocal Is there anything new about indexes in MongoDB 4.2 that I should be aware of?
  • 4. #MDBLocal { "_id" : ObjectId("5c1d358bf383fbee028aea0b"), "product_name" : "Blaster Gauntlet", "product_attributes" : { "elements" : [ "Fire" , "Water" ], "price" : 250 ... } }, { "_id" : ObjectId("5c1d358bf383fbee028aea0c"), "product_name" : "Super Suit", "product_attributes" : { "superFlight" : true, "resistance" : [ "Bludgeoning", "Piercing", "Slashing" ] ... }, } Wildcard Indexes Allow more natural data modeling, avoids pre-defining indexes for every access pattern Polymorphic document structures: Product catalogs, CMS Ad-hoc queries & data exploration Define a filter that indexes all matching fields, sub-documents, and arrays Sparse index, omit specific fields Covered queries & collations Strongly consistent: updated atomically with base data Index all sub-documents & arrays under Product Attributes
  • 5. #MDBLocal I identified slow queries. What index do I make?
  • 6. #MDBLocal Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 7. #MDBLocal Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 9. #MDBLocal E-S-R The ordering of index keys in a compound index is critically important.
  • 10. #MDBLocal E-S-R The ordering of index keys in a compound index is critically important. Does it really matter?
  • 11. #MDBLocal 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
  • 12. #MDBLocal 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?
  • 13. #MDBLocal 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]"
  • 14. #MDBLocal 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]"
  • 15. #MDBLocal Definitions Equality Fields Sort Range Predicates Any predicates that are not exact matches. Some operators include: • {z:{$gt:9000}} • {z:{$lte:1000}} Bounds: "[9000.0, inf.0]", The (entire) requested sort. .sort({a:1, b:-1}) Bounds: "[MinKey, MaxKey]", "[MinKey, MaxKey]" An exact match on a single value. For example: • {x:123} • {x:{$eq:123}} • {"x.y":123} Bounds: "[123.0, 123.0]"
  • 16. #MDBLocal Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 17. #MDBLocal 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.
  • 18. #MDBLocal 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?
  • 19. #MDBLocal 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}} )
  • 20. #MDBLocal 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
  • 21. #MDBLocal 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}
  • 22. #MDBLocal 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 db.games.createIndex({score:1, gamertag:1})
  • 23. #MDBLocal 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})
  • 24. #MDBLocal 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})
  • 25. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 26. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 27. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 28. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 29. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 30. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 31. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "["Ace", "Ace"]" ] } gamertag score db.games.createIndex({score:1, gamertag:1})
  • 32. #MDBLocal 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})
  • 33. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality
  • 34. #MDBLocal 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})
  • 35. #MDBLocal 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})
  • 36. #MDBLocal 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})
  • 37. #MDBLocal 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } gamertag score db.games.createIndex({gamertag:1, score:1})
  • 38. #MDBLocal 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } gamertag score db.games.createIndex({gamertag:1, score:1})
  • 39. #MDBLocal 100 Ace Bob 99,999 15,000 50,000 db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) {} {} {} {} Equality "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "score" : [ "(9000.0, inf.0]" ], } gamertag score db.games.createIndex({gamertag:1, score:1})
  • 40. #MDBLocal 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})
  • 41. #MDBLocal db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Equality before Range
  • 42. #MDBLocal Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 43. #MDBLocal 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
  • 44. #MDBLocal 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})
  • 45. #MDBLocal 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. #MDBLocal 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})
  • 47. #MDBLocal 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})
  • 48. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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})
  • 53. #MDBLocal Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 54. #MDBLocal Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 55. #MDBLocal Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 56. #MDBLocal Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 57. #MDBLocal Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 58. #MDBLocal Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "score" : [ "[MinKey, MaxKey]" ], "gamertag" : [ "["Ace", "Ace"]” ] } db.games.createIndex({score:1, gamertag:1})
  • 59. #MDBLocal 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})
  • 60. #MDBLocal Sort 100 15,000 50,000 99,999 Ace Bob Bob Ace {1} {} {} {2} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} )
  • 61. #MDBLocal 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})
  • 62. #MDBLocal Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 63. #MDBLocal Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 64. #MDBLocal Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 65. #MDBLocal Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 66. #MDBLocal Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 67. #MDBLocal Sort 100 Ace Bob 99,999 15,000 50,000 {}{1} {2} {} db.games.find( {gamertag: "Ace"} ).sort( {score: 1} ) gamertag score "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], ”score" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({gamertag:1, score:1})
  • 68. #MDBLocal 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})
  • 69. #MDBLocal 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
  • 70. #MDBLocal Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 71. #MDBLocal 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
  • 72. #MDBLocal db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Range after Equality
  • 73. #MDBLocal db.games.find( {gamertag: "Ace", score: {$gt: 9000}} ) R E R E Range after Equality Should range come after sort too?
  • 74. #MDBLocal R E R E Range after Equality Should range come after sort too? db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
  • 75. #MDBLocal R E R E Range db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1})
  • 76. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Bob Ace * db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score db.games.createIndex({ …, score:1, gamertag:1})
  • 77. #MDBLocal 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})
  • 78. #MDBLocal 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})
  • 79. #MDBLocal 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})
  • 80. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 81. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 82. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 83. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 84. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 85. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 86. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 87. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 88. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range gamertag score "indexBounds" : { *, "score" : [ "(9000.0, inf.0]" ], "gamertag" : [ "[MinKey, MaxKey]" ] } db.games.createIndex({ …, score:1, gamertag:1})
  • 89. #MDBLocal 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})
  • 90. #MDBLocal {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range Blocking SortBlocking Sort BS
  • 91. #MDBLocal {2}{3}{1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range BS
  • 92. #MDBLocal 100 15,000 50,000 99,999 Ace Bob Cali Ace * {} {2} {3} {1} db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range
  • 93. #MDBLocal db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range * Ace Bob Cali Ace 100 15,000 50,00099,999 {} {1} {2} {3} db.games.createIndex({ …, gamertag:1, score:1})
  • 94. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 95. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 96. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 97. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 98. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 99. #MDBLocal * 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. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 101. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 102. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 103. #MDBLocal * 100 15,000 50,00099,999 Ace Bob Cali db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range {} {1} {3} score gamertag "indexBounds" : { *, "gamertag" : [ "[MinKey, MaxKey]" ] "score" : [ "(9000.0, inf.0]" ] } db.games.createIndex({ …, gamertag:1, score:1}) {2}
  • 104. #MDBLocal * 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}
  • 105. #MDBLocal BS R S R S db.games.find({*, score: {$gt: 9000}}).sort({gamertag: 1}) Range after Sort
  • 106. #MDBLocal Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 107. #MDBLocal Operator Type Check Some operators are simple $eq: Equality $gte: Range Others are trickier
  • 108. #MDBLocal Operator Type Check - Inequality Inequality Operators: E, S, or R? • $ne:123 • $nin:[1,2] Range!
  • 109. #MDBLocal Operator Type Check - Inequality Inequality Operators: E, S, or R? • $ne:123 • $nin:[1,2] Range! How do you know?
  • 110. #MDBLocal Operator Type Check - Inequality Inequality Operators: E, S, or R? • $ne:123 • $nin:[1,2] Range! "indexBounds" : { "x" : [ "[MinKey, 123.0)", "(123.0, MaxKey]" ] }
  • 111. #MDBLocal Operator Type Check - Inequality Range! "indexBounds" : { "x" : [ "[MinKey, 123.0)", "(123.0, MaxKey]" ] } 50 123 999
  • 112. #MDBLocal Operator Type Check - Inequality Range! "indexBounds" : { "x" : [ "[MinKey, 123.0)", "(123.0, MaxKey]" ] } 50 123 999
  • 113. #MDBLocal Operator Type Check - Inequality Range! "indexBounds" : { "x" : [ "[MinKey, 123.0)", "(123.0, MaxKey]" ] } 50 123 999
  • 114. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range!
  • 115. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range!
  • 116. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! planecar racecar
  • 117. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! planecar racecar
  • 118. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! planecar racecar
  • 119. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! p???ecar racecar
  • 120. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! p???ecar racecar
  • 121. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range!
  • 122. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry
  • 123. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry
  • 124. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry Carpool
  • 125. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry Carpool
  • 126. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! raincarry Carpool
  • 127. #MDBLocal 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. #MDBLocal 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?
  • 129. #MDBLocal 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. #MDBLocal 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?
  • 131. #MDBLocal Operator Type Check - Regex Regex Operators: E, S, or R? • {str:/car/} • {str:/^car/i} Range! cArrycarry Carpool
  • 132. #MDBLocal 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
  • 133. #MDBLocal Operator Type Check - $in .find({field:{$in:[1,3]}})
  • 134. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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})
  • 140. #MDBLocal 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})
  • 141. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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})
  • 145. #MDBLocal 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. #MDBLocal 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})
  • 147. #MDBLocal 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. #MDBLocal 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})
  • 149. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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})
  • 154. #MDBLocal 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})
  • 155. #MDBLocal 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. #MDBLocal 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. #MDBLocal 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})
  • 158. #MDBLocal 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})
  • 160. #MDBLocal Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 161. #MDBLocal 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” })
  • 163. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) db.games.createIndex({gamertag:1, date:1, game:1})
  • 164. #MDBLocal 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})
  • 165. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 166. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 167. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 168. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 169. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 170. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 171. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 172. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 173. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 174. #MDBLocal Consecutive Index Keys Ace Mario Halo 2016 2017 Mario Halo 2018 2019 .find({ gamertag:"Ace", game: "Halo” }) {} {} "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[MinKey, MaxKey]" ], "game" : [ "["Halo", "Halo"]" ] } {} {} db.games.createIndex({gamertag:1, date:1, game:1})
  • 175. #MDBLocal 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})
  • 176. #MDBLocal 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, date:1, game:1})
  • 177. #MDBLocal 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, date:1, game:1})
  • 178. #MDBLocal R E E E E E E Consecutive Index Keys R Look familiar? This is equality after range!
  • 179. #MDBLocal Roadmap E-S-R Overview Guidelines: • Eà R • Eà S • Sà R E-S-R Considerations Operator Type Checks Consecutive Index Keys Exceptions?
  • 180. #MDBLocal 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. #MDBLocal 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})
  • 182. #MDBLocal 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})
  • 183. #MDBLocal 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})
  • 184. #MDBLocal 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})
  • 185. #MDBLocal 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})
  • 186. #MDBLocal 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})
  • 187. #MDBLocal 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})
  • 188. #MDBLocal 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})
  • 189. #MDBLocal 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})
  • 190. #MDBLocal 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})
  • 191. #MDBLocal 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})
  • 192. #MDBLocal 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})
  • 193. #MDBLocal 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})
  • 194. #MDBLocal 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})
  • 195. #MDBLocal 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})
  • 196. #MDBLocal 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, {1} {2} db.games.createIndex({gamertag:1, score:1, date:1})
  • 198. #MDBLocal 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})
  • 199. #MDBLocal 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})
  • 200. #MDBLocal 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})
  • 201. #MDBLocal 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})
  • 202. #MDBLocal 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})
  • 203. #MDBLocal 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})
  • 204. #MDBLocal 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, "indexBounds" : { "gamertag" : [ "["Ace", "Ace"]" ], "date" : [ "[2019.0, inf.0]" ] } db.games.createIndex({gamertag:1, date:1})
  • 207. #MDBLocal 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: • Indexing is important from day one, things get slow as the data grows • 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 M201: Performance in MongoDB university.mongodb.com