MST

星途 面试题库

面试题:MongoDB聚合框架在复杂实时数据分析场景中的优化

在一个电商平台的实时数据分析场景中,MongoDB集合存储了订单信息,包括订单ID、用户ID、下单时间、订单金额、商品类别等字段。要求实时计算每个用户在过去一周内,每个商品类别下的平均订单金额,并且只返回平均订单金额大于100的结果。请阐述实现思路并编写聚合管道,同时说明可能存在的性能瓶颈及优化方案。
13.9万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 筛选过去一周的订单:使用$match阶段,通过比较下单时间字段与当前时间减去一周时间,筛选出过去一周内的订单。
  2. 按用户ID和商品类别分组:使用$group阶段,根据用户ID和商品类别进行分组,并计算每组的订单金额总和与订单数量。
  3. 计算平均订单金额:在$group阶段中,用订单金额总和除以订单数量,得到每个用户在每个商品类别下的平均订单金额。
  4. 筛选平均订单金额大于100的结果:使用$match阶段,过滤出平均订单金额大于100的文档。

聚合管道

[
    {
        $match: {
            // 假设下单时间字段为orderTime,这里计算过去一周的时间
            orderTime: {
                $gte: new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000)
            }
        }
    },
    {
        $group: {
            _id: {
                userId: "$userId",
                category: "$category"
            },
            totalAmount: { $sum: "$orderAmount" },
            orderCount: { $sum: 1 }
        }
    },
    {
        $addFields: {
            averageAmount: { $divide: ["$totalAmount", "$orderCount"] }
        }
    },
    {
        $match: {
            averageAmount: { $gt: 100 }
        }
    }
]

可能存在的性能瓶颈及优化方案

性能瓶颈

  1. 大数据量筛选:如果数据量巨大,$match阶段筛选过去一周的订单可能会较慢,因为可能需要全表扫描。
  2. 分组计算$group阶段对大量数据进行分组和计算,可能会消耗较多内存和CPU资源。

优化方案

  1. 索引优化:对orderTime字段建立索引,这样在$match阶段可以利用索引快速筛选出符合条件的订单。
  2. 分片:如果数据量非常大,可以考虑对集合进行分片,将数据分布在多个节点上,提高并行处理能力,减少单个节点的负载。例如按用户ID进行分片,在分组计算时可以并行处理不同分片的数据。
  3. 使用内存计算:如果服务器内存足够,可以利用内存计算框架(如Redis)来缓存部分计算结果,减少对MongoDB的直接查询压力。比如先在Redis中统计订单金额总和与订单数量,然后再传递到MongoDB进行最终的平均计算和筛选。