MongoDBの主キーはあなたの友達です

MongoDBコレクション内のすべてのドキュメントには、主キーがダビングされてい_idます。このフィールドは挿入時にドキュメントに自動的に割り当てられるため、入力する必要はほとんどありません。この_idフィールドで興味深いのは、時間ベースであるということです。つまり、の基になるタイプで_idあるはObjectId12バイトのBSONタイプであり、これらのバイトのうち4バイトはUnixエポックからの秒数を表します。

この_idフィールドの特別な点は、getIndexesコレクションを呼び出すことで以下に示すように、自動的にインデックスが作成されることです。

1 2 3 4 5 6 7 8 9 10 11 
> db.things.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.things", "name" : "_id_" } ] 

また、従来のRDBMSで誰もが覚えているように、インデックスはドキュメントの取得を高速化できるため重要です。それでも、インデックスはメモリを消費し、対応するすべてのインデックスを更新する必要があるため、ドキュメントを挿入するときにパフォーマンスがわずかに低下します。したがって、インデックスの使用を真剣に検討する必要がありますが、インデックスの使用は経済的である必要があります。

当然のことながら、ドキュメントによる検索は、それ_id知っている場合にのみ便利です。多くの場合、ドキュメントは他のフィールドを介して検索されます。たとえば、時系列を介して検索していることに気付いたcreated_at場合は、ご馳走になります。

logsさまざまなログメッセージをキャプチャする単純なドキュメントを含むダビングされたコレクションを想像してみてください。サンプルドキュメントは次のようになります。

1 2 3 4 5 6 
{ "_id" : ObjectId("51c4ab6d4d6906d494460728"), "message" : "crashed, no such method exception", "type" : "crash", "created_at" : ISODate("2013-06-21T19:37:17.992Z") } 

今日のように、ある日付のすべてのログメッセージを検索したい場合はどうすればよいですか?私は次のようにクエリを書くことができます:

1 
db.logs.find({created_at:{'$gt': new Date(2013, 5, 20)}}) 

そのクエリにExplainをスローすると、にインデックスがないためcreated_at、基本的なカーソルが利用され、結果を取得するためにコレクション内のすべてのドキュメントがスキャンされたことがわかります。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
> db.logs.find({created_at:{'$gt': new Date(2013, 5, 20)}}).explain() { "cursor" : "BasicCursor", "isMultiKey" : false, "n" : 2, "nscannedObjects" : 4, "nscanned" : 4, "nscannedObjectsAllPlans" : 4, "nscannedAllPlans" : 4, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { }, "server" : "ghome-computer.home:27017" } 

ご覧のとおり、created_atフィールドを介した検索は非効率的です。したがって、そのフィールドにインデックスをスローしたくなるかもしれません。これにより、当然、その特定のクエリがより効率的になりますが、新しいインデックスのコストが発生し、より多くのメモリが消費され、新しく作成されたインデックスの更新により、挿入がわずかに遅くなります。

_id結局のところ、フィールドにはUnixエポックが埋め込まれているため、フィールド含めなくても、検索式簡単に作成できcreated_atます。たとえば、MongoDB Rubyドライバーを使用するとObjectId、次のTimeようなものからを作成できます。