翻译或纠错本页面

创建能确保选择力的查询

选择力是查询使用索引来缩窄结果集范围的能力。选择力使得MongoDB可以使用索引来完成匹配查询过程中的更多工作。

为了确保选择力,请在查询中使用被索引键来限制可能(扫描)的文档的数量。创建正确的有选择力的查询语句,与您的被索引数据相关。

例子

假设您有一个键 status 可能的值为 newprocessed 。如果您在 status 上创建索引,那么这是一个低选择力的索引。这个索引在定位记录方面可能没多大用处。

更好的策略是,创建一个 复合索引 其中包含了低选择力的键和其它键,这取决于您的查询。例如,您可以在 statuscreated_at 上创建复合索引。

另一种选择,则是针对每种不同的status建立一个集合,这取决于您的使用情况。

例子

假设集合中有一个索引 { a : 1 } (比如,这个键 a 按递增序存储),其中 a 有三个值,在集合上均匀分布:

{ _id: ObjectId(), a: 1, b: "ab" }
{ _id: ObjectId(), a: 1, b: "cd" }
{ _id: ObjectId(), a: 1, b: "ef" }
{ _id: ObjectId(), a: 2, b: "jk" }
{ _id: ObjectId(), a: 2, b: "lm" }
{ _id: ObjectId(), a: 2, b: "no" }
{ _id: ObjectId(), a: 3, b: "pq" }
{ _id: ObjectId(), a: 3, b: "rs" }
{ _id: ObjectId(), a: 3, b: "tv" }

如果您使用查询 { a: 2, b: "no" } ,MongoDB需要在集合中扫描3篇 documents 然后返回一个匹配结果。类似地,查询 { a: { $gt: 1}, b: "tv" } 需要扫描6篇,最后也返回一个结果。

假设在某个集合上有个类似的索引, a 种值在集合上均匀分布:

{ _id: ObjectId(), a: 1, b: "ab" }
{ _id: ObjectId(), a: 2, b: "cd" }
{ _id: ObjectId(), a: 3, b: "ef" }
{ _id: ObjectId(), a: 4, b: "jk" }
{ _id: ObjectId(), a: 5, b: "lm" }
{ _id: ObjectId(), a: 6, b: "no" }
{ _id: ObjectId(), a: 7, b: "pq" }
{ _id: ObjectId(), a: 8, b: "rs" }
{ _id: ObjectId(), a: 9, b: "tv" }

如果您查询 { a: { $gt: 1}, b: "tv" } ,MongoDB值需要扫描一篇文档来满足查询语句。这里的索引和查询语句有更高的选择力,因为这里 a 的值是均匀分布, 并且 查询语句可以使用索引来选择特定的文档。

但是,虽然在 a 上的索引更具选择力,类似于 { a: { $gt: 5 }, b: "tv" } 这样的查询仍然需要扫描4篇文档。

如果所有键的选择力都很低,而且MongoDB必须读取一定数量的文档来返回结果,那么某些查询在没有索引的情况下可能会运行地更快。可以参见 衡量索引的使用情况 来确定索引性能。