You are on page 1of 42

Indexing

Alvin  Richards  -­‐  alvin@10gen.com

Wednesday, May 25, 2011 1


What’s Easy About MongoDB
Indexing?

It’s  almost  the  same  as  in  your  RDBMS

Wednesday, May 25, 2011 2


What’s Hard About MongoDB
Indexing?

It’s  almost  the  same  as  in  your  RDBMS

Wednesday, May 25, 2011 3


Indexes Maintain Order
Index  on  a:  ascending

{a:  0,  b:  9}


{a:  2,  b:  0}
{a:  3,  b:  2}
{a:  3,  b:  7}
{a:  3,  b:  5}
{a:  7,  b:  1}
{a:  9,  b:  1}

Wednesday, May 25, 2011 4


Indexes Maintain Order
Index  on  a:  ascending,  b:  descending

{a:  0,  b:  9}


{a:  2,  b:  0}
{a:  3,  b:  7}
{a:  3,  b:  5}
{a:  3,  b:  2}
{a:  7,  b:  1}
{a:  9,  b:  1}

Wednesday, May 25, 2011 5


Query for {a: 7}
Index  on  a:  ascending
With  Index

∞,  5)
[-­‐
[5,  10)
[10,   ∞)

∞,  5)  buckets
[-­‐
[5,  7) [7,  9) [9,  10)
[10,   ∞)  buckets

{...}  {...}  {...}  {...}  {...}  {...}  {...}  {...}  {...}  {...}  {...}

Without  index  -­‐  Scan

Wednesday, May 25, 2011 6


Creating Indexes
An  index  on  _id  is  automatic.

For  more  use  ensureIndex:

db.blogs.ensureIndex({author:  1})

1  =  ascending
-­‐1  =  descending

Wednesday, May 25, 2011 7


Compound Indexes

db.blogs.save({
   author:  "James",
   ts:  new  Date()
});

db.blogs.ensureIndex({author:  1,  ts:  -­‐1})

Wednesday, May 25, 2011 8


Unique Indexes

db.blogs.save({
   ...
   title:  "My  first  blog"
});  

db.blogs.ensureIndex({title:  1},  {unique:  true})

Wednesday, May 25, 2011 9


Indexing Embedded Documents
db.blogs.save({
   ...
   stats  :  {  views:  0,  
                       followers:  0  }
});

db.blogs.ensureIndex({"stats.followers":  -­‐1})

db.blogs.find({"stats.followers":  {$gt:  500}})

Wednesday, May 25, 2011 10


Indexing Embedded Arrays
db.blogs.save({
   ...
   comments:  [  
       {author:  "James",  ts  :  new  Date()}  ]
});

db.blogs.ensureIndex({"comments.author":  1})

db.blogs.find({"comments.author":  "James"})

Wednesday, May 25, 2011 11


Multikeys
db.blogs.save({
   ...
   tags:  ["mongodb",  "NoSQL"]
});

db.blogs.ensureIndex({tags:  1})

db.blogs.find({tags:  "NoSQL"})

Wednesday, May 25, 2011 12


Covered Indexes
• New in 1.8
• Query resolved in index only
• Need to exclude _id from items projected
db.blogs.save({
   ...
   author:  "James",
});  

db.blogs.ensureIndex({author:  1})

db.blogs.find({author:  "James"},
                           {author:  1,  _id:0}))

Wednesday, May 25, 2011 13


Sparse Indexes
• New in 1.8
• Key value included if and only if the value is present
• Reduces size of index
• Limited to a single field
db.blogs.ensureIndex({loc:  1},  {sparse:  true})

//  loc  key  stored  for  Ben  &  Sarah  only


db.blogs.save({author:  "Jim"})
db.blogs.save({author:  "Ben",  loc:  null})
db.blogs.save({author:  "Sarah",  loc:  "CA"})

Wednesday, May 25, 2011 14


Unique Sparse Indexes
• Null and not-present are different
db.blogs.ensureIndex({url:1},
                                         {sparse:true,unique:true});

db.blogs.save({url:"www.10gen.com"})                                        

//  Can  only  have  a  single  null  value


db.blogs.save({url:null})                                                              
db.blogs.save({url:null})
E11000  duplicate  key  error  index:
     test.blogs.$url_1    dup  key:  {  :  null  }

//  Can  have  multiple  missing  values


db.blogs.save({author:"James"})
db.blogs.save({author:"Bob"})

Wednesday, May 25, 2011 15


Geospatial
• Geo hash stored in B-Tree
• First two values indexed
db.blogs.save({
   loc:  {  long:  40.739037,  lat:  40.739037  }
});

db.blogs.save({
   loc:  [40.739037,  40.739037]
});

db.blogs.ensureIndex({"loc":  "2d"})

Wednesday, May 25, 2011 16


Other Index Operations

db.blogs.getIndexes()

db.blogs.totalIndexSize()

db.blogs.dropIndex({"author":  1})

Wednesday, May 25, 2011 17


When is an Index Used?
Index  on  {a:  1}
db.c.find({a:  0})
db.c.find({a:  {$in:  [0,  2]}})
db.c.find({a:  {$gt:  5}})
db.c.find().sort({a:  -­‐1})
db.c.find({a:  0},  {a:1,  _id:0})
db.c.count({a:  0})
db.c.find({loc:  {$near:  [50,50]  }})
Partially:
db.c.find({b:  0}).sort({a:  -­‐1})

Wednesday, May 25, 2011 18


When isn’t an Index Used?
Index  on  {a:  1,  b:  -­‐1}

db.c.find({b:  0})
db.c.find({a:  {$ne:  1}  })
db.c.find({a:  {$nin:  [1,  3,  5,  7]}  })

Wednesday, May 25, 2011 19


Picking an index
db.c.ensureIndex({x:1})
db.c.ensureIndex({y:-­‐1})

db.c.find({x:  10,  y:  “foo”})

   scan

terminated
   index  on  x

   index  on  y remember

Wednesday, May 25, 2011 20


When are Indexes Needed?
•Frequently  used  queries
•Low  response  time
•Avoid  full  collection  scans

Wednesday, May 25, 2011 21


Indexes Slow Down Writes

•Indexes  take  up  space


•Index  maintenance  will  cause  writes

Wednesday, May 25, 2011 22


Does my query use an Index?

db.blogs.find({title:"My  blog"}).explain();

Wednesday, May 25, 2011 23


Explain - Scan all documents

db.blogs.find({title:"My  blog"}).explain();

{
       "cursor"  :  "BasicCursor",
       "indexBounds"  :  {}
       "nscanned"  :  57594,
       "nscannedObjects"  :  57594,
       "n"  :  3,
       "millis"  :  108
}

Wednesday, May 25, 2011 24


Explain - Index used

db.blogs.ensureIndex({title:  1});
db.blogs.find({title:  "My  blog"}).explain();
{
       "cursor"  :  "BtreeCursor  x_1",
       "indexBounds"  :  {...},
       "nscanned"  :  123,
       "nscannedObjects"  :  123,
       "n"  :  10,
       "millis"  :  4
}

Wednesday, May 25, 2011 25


Explain - Covered Index used

db.blogs.ensureIndex({title:  1});
db.blogs.find({title:  "My  blog"},
                           {title:  1,  _id:  0}).explain();
{
       "cursor"  :  "BtreeCursor  x_1",
       "indexBounds"  :  {...},
       "nscanned"  :  123,
       "nscannedObjects"  :  123,
       "n"  :  10,
       "millis"  :  4,
       "indexOnly"  :  true
}

Wednesday, May 25, 2011 26


Index Internals - Equality match
db.c.find({x:  6})

1 2 3 4 5 6 6 6 9

{_id:4,x:6} {_id:5,x:6}

{_id:1,x:6}
Wednesday, May 25, 2011 27
Equality match
db.c.find({x:6}).explain()
{
  "cursor"  :  "BtreeCursor  x_1",
  "nscanned"  :  3,
  "nscannedObjects"  :  3,
  "n"  :  3,
  "millis"  :  1,
  "nYields"  :  0,
  "nChunkSkips"  :  0,
  "isMultiKey"  :  false,
  "indexOnly"  :  false,
  "indexBounds"  :  {
    "x"  :  [
      [
        6,
        6
      ]
    ]
  }
}

Wednesday, May 25, 2011 28


Equality match
  "indexBounds"  :  {
    "x"  :  [
      [
        6, Exact match will
have an inclusive
        6
range
      ]
    ]
  }

Wednesday, May 25, 2011 29


Equality match
  "nscanned"  :  3,
  "nscannedObjects"  :  3,
  "n"  :  3, Number of matching
  documents is 3

Wednesday, May 25, 2011 30


Equality match
db.c.find({x:  6})
5

2 6

1 3 4 6 6 9

Wednesday, May 25, 2011 31


Full document match
db.c.ensureIndex({x:  1})
db.c.find({x:  6,  y:  1})

1 2 3 4 5 6 6 6 9

{y:4,x:6} {y:5,x:6}

{y:1,x:6}
Wednesday, May 25, 2011 32
Full document match
db.c.find({x:  6,  y:  1}).explain()
{
  "cursor"  :  "BtreeCursor  x_1",
  "nscanned"  :  3,
  "nscannedObjects"  :  3,
  "n"  :  1,
  "millis"  :  1,
  "nYields"  :  0,
  "nChunkSkips"  :  0,
  "isMultiKey"  :  false,
  "indexOnly"  :  false,
  "indexBounds"  :  {
    "x"  :  [
      [
        6,
        6
      ]
    ]
  }
}

Wednesday, May 25, 2011 33


Full document match
"indexBounds" : {
"x" : [
[
6, Exact match will
have an inclusive
6
range
]
]
}

Wednesday, May 25, 2011 34


Full document match
  "nscanned"  :  3,
  "nscannedObjects"  :  3,
Documents for all
  "n"  :  1,
matching keys
scanned, but only
one document
matched on non-
index keys

Wednesday, May 25, 2011 35


Range match
db.c.ensureIndex({x:  1})
db.c.find({x:{$gte:4,  $lte:7}})

1 2 3 4 5 6 7 8 9

Wednesday, May 25, 2011 36


Range match
db.c.find(  {x:{$gte:4,$lte:7}}  ).explain()
{
  "cursor"  :  "BtreeCursor  x_1",
  "nscanned"  :  4,
  "nscannedObjects"  :  4,
  "n"  :  4,
  "millis"  :  1,
  "nYields"  :  0,
  "nChunkSkips"  :  0,
  "isMultiKey"  :  false,
  "indexOnly"  :  false,
  "indexBounds"  :  {
    "x"  :  [
      [
        4,
        7
      ]
    ]
  }
}

Wednesday, May 25, 2011 37


Range match
"indexBounds"  :  {
    "x"  :  [
      [
        4, Range match will
have an inclusive
        7
range
      ]
    ]

Wednesday, May 25, 2011 38


Range match
  "nscanned"  :  4,
  "nscannedObjects"  :  4,
  "n"  :  4, Number of matching
documents is 4

Wednesday, May 25, 2011 39


Range match

2 7

1 3 4 6 8 9

Wednesday, May 25, 2011 40


Mongostat

insert    query  update  delete  getmore  command  flushes  mapped    vsize        res  locked  %  idx  miss  %      
   5345            0            0            0              0              1              0    8.75g    11.1g      132m                1                    2      
     230            0            0            0              0              1              0    8.75g    11.1g      132m                1                    7      
   1740          20            0            0              0              2              0    8.75g    11.1g      132m                3                  19  
         0        120            0            0              0              1              0    8.75g    11.1g      132m                0                  17  
         0        117            0            0              0              1              0    8.75g    11.1g      132m                0                  16  
         0        119            0            0              0              1              0    8.75g    11.1g      132m                0                  17  
   

Wednesday, May 25, 2011 41


download at mongodb.org

We’re Hiring !
alvin@10gen.com

conferences,  appearances,  and  meetups


http://www.10gen.com/events

Facebook                    |                  Twitter                  |                  LinkedIn


http://bit.ly/mongoF   @mongodb http://linkd.in/joinmongo

Wednesday, May 25, 2011 42

You might also like