mongodbを使ってみる (3) - インデックスに関して -
ちょいとインデックスの使い方な感じでやってみる
db.samples.save({ name: "hoge", tags: ["A"] })
db.samples.save({ name: "fuga", tags: ["A", "B"] })
db.samples.save({ name: "foobar", tags: ["B", "C"] })
な感じで突っ込んでおいて、普通にキーに対する値の型が配列型でも
db.samples.find({ tags: "A" })
っていう感じで検索は出来る。出力が
{ "_id" : ObjectId("50f475453f2dbe87db25fd00"), "name" : "hoge", "tags" : [ "A" ] }
{ "_id" : ObjectId("50f475533f2dbe87db25fd01"), "name" : "fuga", "tags" : [ "A", "B" ] }
でどういうインデックスが使われてるかとかexplainで見れるらしいので
db.samples.find({ tags: "A" }).explain()
でやると
{
"cursor" : "BasicCursor",
"nscanned" : 3,
"nscannedObjects" : 3,
"n" : 2,
"millis" : 17,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
多分、indexBoundsが無いっていう事でインデックスが使われてない。っていうかそもそもインデックス自体作ってない
db.samples.ensureIndex({ tags: 1 })
でtagsキーに対してインデックスを作る。何やらドキュメントによるとensureIndexが同期型であり、インデックス作成が完了するまでは操作をブロックする模様(db.currentOp で見れるとか)。その場合には第2引数で、{ background: true }な感じで作ればインデックスをバックグラウンドで作成するようになる模様。但し、マスター/スレーブな構成とかで使ってる場合にはこれを指定した所でもスレーブ側は完了するまで操作ブロックされるみたい。検証してないから微妙だけど
という感じでもう一回explainしてみると
{
"cursor" : "BtreeCursor tags_1",
"nscanned" : 2,
"nscannedObjects" : 2,
"n" : 2,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"tags" : [
[
"B",
"B"
]
]
}
}
な感じの結果になる。配列型にインデックスをつけるとmultikeysタイプになる模様なのでisMultiKeyがtrueになる的な感じかと
追記
ensureIndexに指定出来るキーと値についてドキュメントによると、キーはインデックスを適応するキー名であり、値が1であれば昇順、-1であれは降順になる模様
db.samples.insert({ name: "hoge", type: 1 })
db.samples.insert({ name: "fuga", type: 1 })
db.samples.insert({ name: "foobar", type: 1 })
というデータつっこんどいて
db.samples.ensureIndex({ type: 1, name: 1 })
っていうインデックスを突っ込んで、find({ type: 1 })すると
{ "_id" : ObjectId("50f4c6fe65d2c24c46dd38a9"), "name" : "foobar", "type" : 1 }
{ "_id" : ObjectId("50f4c6f465d2c24c46dd38a8"), "name" : "fuga", "type" : 1 }
{ "_id" : ObjectId("50f4c6eb65d2c24c46dd38a7"), "name" : "hoge", "type" : 1 }
という結果になる。もし、nameにインデックス適応させなかったら
{ "_id" : ObjectId("50f4c6eb65d2c24c46dd38a7"), "name" : "hoge", "type" : 1 }
{ "_id" : ObjectId("50f4c6f465d2c24c46dd38a8"), "name" : "fuga", "type" : 1 }
{ "_id" : ObjectId("50f4c6fe65d2c24c46dd38a9"), "name" : "foobar", "type" : 1 }
というようにインデックスによるソートが反映されない。自前でsortすれば良いって話にもなるかも知らないけど