创建选择性索引以高效地回答查询
在此页面上
选择性是一个查询属性,描述与查询匹配的文档与集合中文档总数的比率。索引的选择性描述了唯一索引键匹配的文档数量。当与查询或给定索引键匹配的文档相对较少时,查询或索引具有较高的选择性。
由于索引可能具有不同的选择性,具体取决于所使用的索引键,因此请确保根据查询中包含的谓词提供最具选择性的索引。为确保最高效地执行查询,请创建与查询中包含的谓词最匹配的索引。
示例
具有许多共同值时的选择性
请考虑具有以下形式的文档的集合:
{ status: "processed", product_type: "electronics" }
在此示例中,集合中status
99% 的文档的 为processed
。如果您在status
上添加索引并查询status
为processed
的文档,则索引和查询的选择性都很低。但是,如果要查询 status
不为processed
的文档,索引和查询具有很高的选择性,因为查询仅返回集合中文档的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必须读取三个索引键,检索与该状态匹配的三个文档,并在 product_type
上进一步过滤这些文档以返回一个匹配的文档。同样,对 { "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仅读取与索引键匹配的一份文档,这表明该索引具有高度选择性。通过使用此索引,您可以更有效地接收查询响应,因为MongoDB必须仅进一步过滤与索引值匹配的一个文档。在这种情况下,过滤也会匹配,并且查询仅返回一个文档。
尽管此示例对 status
相等性的查询更具选择性,但如果对 status
使用相同的索引,诸如 { "status": { $gt: 5 }, "product_type": "grocery" }
之类的查询仍需读取四个文档。但是,如果在 product_type
和 status
上创建复合索引, MongoDB可以通过复合索引更有效地回答对 {"status": { $gt: 5 }, "product_type": "grocery" }
的查询,因为该查询仅返回一个匹配的文档。
为了提高查询性能,您可以创建 复合索引,以缩小查询读取的文档范围。示例,如果要提高对 status
和 product_type
的查询性能,可以对这两个字段创建复合索引。
如果MongoDB读取相对大量的文档以返回结果,则某些查询在没有索引的情况下可能执行得更快。要确定性能,请参阅测量索引使用情况。