MST

星途 面试题库

面试题:MongoDB聚合框架排序阶段的性能优化及复杂场景处理

在一个大型电商数据库中,有一个集合‘sales’,存储了大量销售记录,每个文档包含‘sale_id’(销售记录ID)、‘timestamp’(销售时间戳)、‘customer_id’(客户ID)、‘total_amount’(销售总金额)等字段。现在需要统计每个客户的总销售额,并按照总销售额降序排列,同时要求考虑到高并发查询场景下聚合排序操作的性能优化,描述你的实现思路及可能用到的索引策略。
27.4万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 聚合操作
    • 使用 MongoDB 的聚合框架 $group 操作符来按 customer_id 对销售记录进行分组,并使用 $sum 累加 total_amount 字段,以得到每个客户的总销售额。
    • 示例代码如下(假设使用 Node.js 和 MongoDB 驱动):
    const { MongoClient } = require('mongodb');
    const uri = "mongodb://localhost:27017";
    const client = new MongoClient(uri);
    async function getTotalSalesPerCustomer() {
        try {
            await client.connect();
            const db = client.db('yourDatabaseName');
            const salesCollection = db.collection('sales');
            const result = await salesCollection.aggregate([
                {
                    $group: {
                        _id: "$customer_id",
                        total_sales: { $sum: "$total_amount" }
                    }
                },
                {
                    $sort: {
                        total_sales: -1
                    }
                }
            ]).toArray();
            return result;
        } finally {
            await client.close();
        }
    }
    getTotalSalesPerCustomer().then(console.log).catch(console.error);
    
  2. 性能优化 - 高并发场景
    • 索引策略
      • customer_idtotal_amount 字段创建复合索引。在 MongoDB 中,可以使用以下命令创建索引:
      await salesCollection.createIndex({ customer_id: 1, total_amount: 1 });
      
      • 该复合索引可以加速 $group 操作中的分组和 $sort 操作中的排序。对于分组操作,索引可以帮助快速定位到属于每个 customer_id 的文档。对于排序操作,由于索引是按照 customer_idtotal_amount 顺序存储的,在按 total_amount 降序排序时可以利用索引结构,减少数据的扫描量。
    • 读写分离:在高并发读场景下,可以使用副本集,将读操作分发到副本节点,减轻主节点的压力。在 MongoDB 中,通过配置副本集,并在应用程序中使用适当的读偏好(如 secondaryPreferred)来实现读写分离。
    • 缓存机制:对于频繁查询的结果,可以使用缓存,如 Redis。在每次查询前先检查缓存中是否有相应的数据,如果有则直接返回,减少数据库的负载。当数据库中的销售数据发生变化时,及时更新缓存。

总结

通过合理利用 MongoDB 的聚合框架,结合适当的索引策略、读写分离和缓存机制,可以在高并发场景下高效地统计每个客户的总销售额并按降序排列。