V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐工具
RoboMongo
推荐书目
50 Tips and Tricks for MongoDB Developers
Related Blogs
Snail in a Turtleneck
Belmode
V2EX  ›  MongoDB

请教大家一个 mongodb 大数据量下, count 优化的问题

  •  
  •   Belmode · 284 天前 · 2007 次点击
    这是一个创建于 284 天前的主题,其中的信息可能已经有所发展或是发生改变。
    问题背景:
    现在有个一个集合,每月大概会往里插入将近 600M 的数据,项目项目上线了将近 4 个月,有 2500W 数据,现在 count 一次,需要将近 1~2 分钟,即使使用了各类索引优化,还是没什么太大作用。

    我想请教一下大家,遇到这中情况,该如何优化呢,或者说,有什么更合适的方案去在这种数据量下进行 count 查询呢?

    谢谢!
    第 1 条附言  ·  283 天前

    大概的查询语句

    集合schema

    {
        //...省略其他字段
        "_id": ObjectId("65e9310b6c21fc6df939c43d"),
        "nodeType": "start",
        "executeTime": ISODate("2024-03-07T03:14:19.708Z"),
        "isDetail": false,
    }
    

    索引

    {
        "executeTime": -1,
        "nodeType": 1,
        "isDetail": 1,
    }
    

    查询语句

    db.collection.countDocuments({
        "executeTime": {
            $gte: new Date(new Date().getTime() - 30 * 24 * 60 * 60 * 1000),
            $lte: new Date()
        },
        "nodeType": "interactive",
        "isDetail": true,
    }, {
      "executeTime": 1
      "nodeType": 1,
      "isDetail": 1,
      "_id": 1,
    })
    
    13 条回复    2024-03-13 13:28:12 +08:00
    Yuan2One
        1
    Yuan2One  
       284 天前 via Android
    只查总数吗,存 redis 可以吗
    rimutuyuan
        2
    rimutuyuan  
       284 天前
    定时去 count 缓存,这么多数据应该不需要实时精确数量吧?
    coderxy
        3
    coderxy  
       284 天前
    这个要看你索引的定义, 一般 count 条件语句的第一个字段非常重要,要用比较稀疏的字段, 还是要具体分析的。 你可以把你的字段和查询条件贴出来,具体分析一下看看。
    defunct9
        4
    defunct9  
       283 天前   ❤️ 1
    开 ssh ,让我上去看看
    lilei2023
        5
    lilei2023  
       283 天前
    @defunct9 你这个光头,每次都要 ssh !
    Belmode
        6
    Belmode  
    OP
       283 天前
    @Yuan2One #1 虽然查询频率很低,但是还是会有条件变化的,redis 不适合这种场景。

    @rimutuyuan #2 查询频率很低,但是条件会变化,所以定时任务也不太行

    @coderxy #3 查询的第一个条件是时间。

    @defunct9 #4 老哥老面孔了

    @lilei2023 #5 上面的老哥是来挽尊的,气氛担当~
    Belmode
        7
    Belmode  
    OP
       283 天前
    @coderxy #3 集合结构和查询语句

    集合 schema
    {
    //...省略其他字段
    "_id": ObjectId("65e9310b6c21fc6df939c43d"),
    "nodeType": "start",
    "executeTime": ISODate("2024-03-07T03:14:19.708Z"),
    "isDetail": false,
    }
    索引
    {
    "executeTime": -1,
    "nodeType": 1,
    "isDetail": 1,
    }

    查询语句
    db.collection.countDocuments({
    "executeTime": {
    $gte: new Date(new Date().getTime() - 30 * 24 * 60 * 60 * 1000),
    $lte: new Date()
    },
    "nodeType": "interactive",
    "isDetail": true,
    }, {
    "executeTime": 1
    "nodeType": 1,
    "isDetail": 1,
    "_id": 1,
    })
    coderxy
        8
    coderxy  
       283 天前
    @Belmode nodeType 存在的值多不多? 多的话拿 nodeType 做联合索引第一位,isDetail=true 的情况多不多,多的话拿 isDetail 做第一位,反正索引要么是 nodeType_isDetail_executeTime 要么是 isDetail_nodeType_executeTime ,你再去试试,性能应该回好不少。 你现在的索引用法,估计 explain 分析一下,seek 特别多。 最终的效果可能相当于只有 executeTime 单索引的效果。
    rrfeng
        9
    rrfeng  
       283 天前 via Android
    这索引没啥可以优化的,只能走预计算了。
    比如把每天的 count 算出来单独存一下,这个查询优化成 sum 29 天 统计数据+本日数据。
    mingsz
        10
    mingsz  
       283 天前
    executeTime 需要查询的那么精确吗,可以新增个字段,如果到天/小时,索引会小很多
    ychost
        11
    ychost  
       283 天前
    这个感觉没太大优化点了,每天提前把所有条件都查一遍吧,然后前端值允许查看预制的筛选条件
    nomagick
        12
    nomagick  
       283 天前
    是不是小内存机械盘?

    起码得用个固态盘。。。
    Belmode
        13
    Belmode  
    OP
       283 天前
    @coderxy @rrfeng @ychost @nomagick 多谢各位了,我去研究研究
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2509 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 03:01 · PVG 11:01 · LAX 19:01 · JFK 22:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.