面试题答案
一键面试索引对聚合操作性能的影响
- 加快查询速度:在聚合操作中,如果某些阶段(如
$match
)的条件字段上有索引,MongoDB 可以利用索引快速定位符合条件的文档,减少全表扫描的开销,从而大大提高聚合操作的执行效率。例如,在一个包含大量用户信息的集合中,若对age
字段建立了索引,当在聚合操作的$match
阶段筛选特定年龄段的用户时,就能利用该索引快速定位文档。 - 减少内存使用:通过索引快速定位数据,避免将大量不必要的数据读入内存,降低了聚合操作对内存的需求。这对于处理大数据集时防止内存溢出等问题非常关键。
常见聚合操作中索引的使用方式及原理
$match
操作- 使用方式:假设我们有一个
products
集合,包含字段category
和price
。若要查找特定类别且价格在一定范围内的产品,我们可以这样写聚合管道:
- 使用方式:假设我们有一个
db.products.aggregate([
{
$match: {
category: "electronics",
price: { $gt: 100 }
}
}
]);
如果在 category
和 price
字段上分别建立了索引(可以是单字段索引,也可以是复合索引 {category: 1, price: 1}
),MongoDB 会利用这些索引快速筛选出符合条件的文档。
- 原理:$match
阶段会按照索引规则,从索引树中快速定位满足条件的文档指针,然后根据指针获取实际文档,而无需遍历整个集合。对于复合索引,MongoDB 会按照索引字段的顺序依次匹配条件,先根据 category
筛选,再在筛选后的结果中根据 price
进一步筛选。
2. $group
操作
- 使用方式:对于 products
集合,若要按 category
分组并统计每个类别的产品数量,聚合管道如下:
db.products.aggregate([
{
$group: {
_id: "$category",
count: { $sum: 1 }
}
}
]);
在这种情况下,如果在 category
字段上有索引,虽然 $group
操作本身不会直接像 $match
那样利用索引来筛选文档,但索引可以加快前期 $match
阶段(如果有的话)对 category
相关条件的筛选,从而间接提高整个聚合操作的性能。例如:
db.products.aggregate([
{
$match: {
price: { $gt: 50 }
}
},
{
$group: {
_id: "$category",
count: { $sum: 1 }
}
}
]);
这里在 price
字段上的索引加快了 $match
阶段的筛选,使得传递到 $group
的数据量减少,提高了整体性能。
- 原理:$group
操作主要是对文档进行分组和计算,本身并不直接依赖索引来完成分组逻辑。但索引通过优化前置 $match
阶段,减少输入到 $group
的数据量,进而提升性能。因为处理的数据量越少,$group
操作的计算开销就越小。