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,  10) [-­‐

∞,  5)

[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:1,x:6}
Wednesday, May 25, 2011

{_id:5,x:6}

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,       6     ]   ] }

Exact match will have an inclusive 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 1 3 4 6 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:1,x:6}
Wednesday, May 25, 2011

{y:5,x:6}

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, 6 ] ] }

Exact match will have an inclusive range

Wednesday, May 25, 2011

34

Full document match
  "nscanned"  :  3,   "nscannedObjects"  :  3,   "n"  :  1,
Documents for all matching keys scanned, but only one document matched on nonindex 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,         7       ]     ]

Range match will have an inclusive 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 5 2 1 3 4 6 7 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

http://bit.ly/mongoF  

Facebook                    |                  Twitter                  |                  LinkedIn
@mongodb

http://linkd.in/joinmongo

Wednesday, May 25, 2011

42

Sign up to vote on this title
UsefulNot useful