创建索引以确保查询选择性
在此页面上
选择性是指查询使用索引缩小结果范围的能力。有效的查询更具选择性,并允许 MongoDB 将索引用于与执行查询相关的大部分工作。
为确保选择性,编写查询时应限制索引字段或字段可能包含的文档数量。根据索引数据编写具有适当选择性的查询。
示例
具有许多共同值时的选择性
请考虑具有以下形式的文档的集合:
{ status: "processed", product_type: "electronics" }
在此示例中,集合中99 % 的文档的 status
为processed
。 如果您在status
上添加索引并查询status
为processed
的文档,则索引对此查询的选择性较低。 但是,如果要查询不具有processed
的status
的文档,此索引具有很高的选择性,因为查询仅读取索引的1 %。
利用分布式值实现选择性
考虑一个文档集合,其中 status
字段有三个值分布在集合中:
[ { _id: ObjectId(), status: "processed", product_type: "electronics" }, { _id: ObjectId(), status: "processed", product_type: "grocery" }, { _id: ObjectId(), status: "processed", product_type: "household" }, { _id: ObjectId(), status: "pending", product_type: "electronics" }, { _id: ObjectId(), status: "pending", product_type: "grocery" }, { _id: ObjectId(), status: "pending", product_type: "household" }, { _id: ObjectId(), status: "new", product_type: "electronics" }, { _id: ObjectId(), status: "new", product_type: "grocery" }, { _id: ObjectId(), status: "new", product_type: "household" } ]
如果在 status
上添加索引并查询 { "status": "pending",
"product_type": "electronics" }
,MongoDB 必须读取三个索引键才能返回一个匹配的结果。同样,对 { "status": {
$in: ["processed", "pending"] }, "product_type" : "electronics" }
的查询必须读取六个文档才能返回两个匹配的文档。
考虑集合上的同一索引,其中 status
拥有 9 个在集合中分布的值:
[ { _id: ObjectId(), status: 1, product_type: "electronics" }, { _id: ObjectId(), status: 2, product_type: "grocery" }, { _id: ObjectId(), status: 3, product_type: "household"}, { _id: ObjectId(), status: 4, product_type: "electronics" }, { _id: ObjectId(), status: 5, product_type: "grocery"}, { _id: ObjectId(), status: 6, product_type: "household"}, { _id: ObjectId(), status: 7, product_type: "electronics" }, { _id: ObjectId(), status: 8, product_type: "grocery" }, { _id: ObjectId(), status: 9, product_type: "household" } ]
如果您查询 { "status": 2, "product_type": "grocery" }
,MongoDB 进读取一个文档来完成查询。索引和查询更具选择性,因为只有一个匹配文档,并且查询可以使用索引选择该特定文档。
尽管此示例对 status
相等性的查询更具选择性,但像 { "status": { $gt: 5 }, "product_type": "grocery" }
这样的查询仍然需要读取四个文档。但是,如果在 product_type
和 status
上创建一个复合索引,对 {
"status": { $gt: 5 }, "product_type": "grocery" }
的查询只需读取两个文档。
为了提高选择性,您可以创建复合索引,以缩小查询读取的文档范围。 示例,如果要提高对status
和product_type
查询的选择性,可以对这两个字段创建复合索引。
如果 MongoDB 要读取大量文档才能返回结果,那么某些查询在没有索引的情况下可能会执行得更快。要确定性能,请参阅测量索引使用情况。