Mongodb稀疏索引和一般索引

时间:2018-01-02 11:45:11

标签: mongodb indexing sparse-matrix

我创建了一个包含100个文档(字段x& y)的集合,并在字段x上创建了一个普通索引,在字段y上创建了一个稀疏索引,如下图所示:

for(i=1;i<100;i++)db.coll.insert({x:i,y:i})

db.coll.createIndex({x:1})
db.coll.createIndex({y:1},{sparse:true})

然后,我添加了一些没有字段的文档x&amp;如下图所示:

for(i=1;i<100;i++)db.coll.insert({z:"stringggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"})

查看db.coll.stats(),我找到了索引的大小:

storageSize:36864
_id:32768
x_1:32768
y_1:16384

根据稀疏索引的定义,只考虑包含索引字段y的文档,因此y_1占用的空间更少。但是_id&amp; x_1索引似乎包含其中的所有文档。

如果我执行查询 - db.coll.find({z:99}).explain('executionStats')

它正在执行COLLSCAN并获取记录。如果是这种情况,我不清楚为什么MongoDB将所有文件存储在_id&amp; x_1索引,因为它浪费了存储空间。请帮我理解。请原谅我的无知,如果我错过了什么。

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

在&#34;正常&#34;索引,缺少的字段使用null值编制索引。例如,如果索引为{a:1}并且您将{b:10}插入集合中,则该文档将被编入索引为a: null

您可以使用唯一索引查看此行为:

> db.test.createIndex({a:1}, {unique:true})
{
    "createdCollectionAutomatically" : true,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

> db.test.insert({b:1})
WriteResult({ "nInserted" : 1 })

> db.test.insert({c:1})
WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "E11000 duplicate key error collection: test.test index: a_1 dup key: { : null }"
    }
})

{b:1}{c:1}都被编入索引a: null,因此出现重复的密钥错误消息。

在您的收藏中,您有200份文件:

  • 包含{x:..., y:...}
  • 的100份文件
  • 包含{z:...}
  • 的100份文件

您的索引是:

  • {x:1}(正常指数)
  • {y:1}(稀疏索引)

文件将编入索引如下:

  • 200个文档将位于_id索引中,该索引始终由MongoDB
  • 创建
  • 200个文档将位于{x:1}索引中,来自{x:.., y:..}{z:..}个文档
  • 100个文档将位于{y:1}索引

请注意,您发布的索引尺寸显示与上述数字相同的比率。

关于你的问题:

  • _id索引用于MongoDB内部使用,请参阅Default _id index。您不能删除此索引,并尝试删除它可能导致您的数据库无法访问。
  • x_1索引是因为您告诉MongoDB构建它。它包含集合中的所有文档,因为它是正常索引。对于您的集合,索引中的一半值为null
  • 稀疏y_1索引的大小是x_1索引的一半,因为200个文档中只有100个包含y字段。
  • 查询db.coll.find({z:99})不使用任何索引,因为您在z字段上没有索引,因此它正在进行收集扫描。

有关建立索引的详细信息,请参阅Create Indexes to Support Your Queries