- Frequently Asked Questions >
- FAQ:索引
FAQ:索引¶
本文是MongoDB索引常见问题的介绍。
如果没有找到你想要的答案,请查看 complete list of FAQs 或者把你的问题提交到 MongoDB User Mailing List 。 也可以参考 索引教程 。
是否需要在每次写入数据后都运行 ensureIndex() ?¶
不需要,对于单个集合你只需要创建一次索引。在创建完成后,MongoDB会随着数据改变而自动更新索引。
尽管通常情况下执行 ensureIndex() 是没有问题的,但是如果一个索引因为持续运行的后台管理工作而没有生成, 这时如果调用 ensureIndex() 将破坏数据库的可用性。运行命令 ensureIndex() 创建索引期间复制集会无法读写。 参见 在复制集上创建索引 。
如何查看集合中已存在哪些索引?¶
使用 db.collection.getIndexes() 方法或你所使用的驱动上的类似 method for your driver 可以列出一个集合上的已创建的所有索引。
你要如何确定索引的大小?¶
使用命令 db.collection.stats() 可以检查集合上的索引所占空间大小。
如果索引不能被装载到内存空间会发生什么?¶
如果索引所占存储空间过大而不能被加载到内存中,MongoDB必须从硬盘读取索引,而硬盘读取索引要远比从内存读取慢得多。注意,索引匹配内存是指你的服务器对索引和其它工作集的组合有足够的可用内存空间 working set
在某些情况下,索引不必 完全 加载到RAM,详细内容参见 只在内存中存储最近的数据的索引 。
如何确定在哪些字段上建立索引?¶
许多因素会决定你在哪些字段上建立索引,包括 selectivity ,内存适配,尽可能地在多个查询中重用索引,和支持给定查询中的所有字段。更详细的文档参见 索引教程 。
写操作是如何影响索引的?¶
任何改变索引中字段的写操作都会既修改文档本身也更新索引。如果你对文档的更新操作导致文档大小超出了已分配的记录大小,那么MongoDB不仅会修改这个文档,还会更新所有的索引。
因此,如果你的程序写操作非常多,创建过多的索引可能会影响性能。
构建一个大型的索引会影响数据库的性能吗?¶
建立索引是一个IO密集型操作,特别是当你的集合很大的时候。包括MySQL在内的所有支持辅助索引的数据库系统都有这种情况。如果你需要在一个大集合上建立索引,可以考虑在后台建立它。参考 索引创建 。
如果你创建一个大索引而且没有选择在后台运行,这时如果导致数据库没有响应,可以按照如下方式解决:
等待索引构建完成。
中断当前的操作(参见 db.killOp() ),部分索引将被删除。
为什么使用 $ne 和 $nin 会导致查询很慢?¶
The $ne and $nin operators are not selective. See 创建能确保选择力的查询. If you need to use these, it is often best to make sure that an additional, more selective criterion is part of the query.
我可以用一个多键索引来支持整个数组的查询?¶
不完全可行。索引可以部分地支持这种查询,因为索引可以加快数组第一个元素的选择,但是不能用索引去比较数组中所有后续的元素,只能通过单独地扫描文档来完成。
我怎样才能有效地使用索引策略来查找属性?¶
对于不需要对结果集进行排序的查询或范围查询,可以考虑创建一个字段,这个字段包含一个由文档组成的数组,数组中每一个文档都有一个保存指定类型属性的字段(比如 attrib )。你可以索引 attrib 字段。
例如,下面文档中的字段 attrib 允许你添加不限数量的属性类型:
{ _id : ObjectId(...),
attrib : [
{ k: "color", v: "red" },
{ k: "shape": v: "rectangle" },
{ k: "color": v: "blue" },
{ k: "avail": v: true }
]
}
下面的 两个 查询都可以使用同样的索引 { "attrib.k": 1, "attrib.v": 1 } :
db.mycollection.find( { attrib: { $elemMatch : { k: "color", v: "blue" } } } )
db.mycollection.find( { attrib: { $elemMatch : { k: "avail", v: true } } } )