V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
LoremIpSum
V2EX  ›  程序员

需求:统计用户首次 XXX 的时间,用户表:百万数据, XXX 表:亿级数据

  •  
  •   LoremIpSum · 2019-09-30 10:24:44 +08:00 · 3666 次点击
    这是一个创建于 1911 天前的主题,其中的信息可能已经有所发展或是发生改变。

    来了几个比较不好处理的需求: 统计用户首次 XXX 的时间,XXX 代表用户行为,可以是评论,发帖,点赞等,XXX 表的数据上亿,用户表也接近百万,直接用 SQL 去查肯定不是很合适,如果要把每个用户首次 XXX 的数据拿出来的话,大概怎么样来跑数据比较合适?

    24 条回复    2019-09-30 22:14:20 +08:00
    liprais
        1
    liprais  
       2019-09-30 10:26:55 +08:00
    为啥直接写 sql 不合适?
    alamaya
        2
    alamaya  
       2019-09-30 10:30:27 +08:00
    没戏,拆表,把用户行为细分,存量数据迁移,只记录最新行为时间
    LoremIpSum
        3
    LoremIpSum  
    OP
       2019-09-30 10:31:56 +08:00
    @liprais

    ```
    SELECT MIN(A.CreateTime) ,A.UserId
    FROM XXX A
    GROUP BY A.UserId
    ```
    大概是这种 SQL,跑起来特别慢
    encro
        4
    encro  
       2019-09-30 10:33:49 +08:00
    stat_by_day:
    date,
    action,
    value
    sadfQED2
        5
    sadfQED2  
       2019-09-30 10:34:11 +08:00
    分表 or 加缓存

    你用 uid 分表不就完事了吗
    arrow8899
        6
    arrow8899  
       2019-09-30 10:40:01 +08:00
    SELECT * FROM (SELECT * FROM actives ORDER BY add_time ASC ) t1 GROUP BY t1.uid, t1.active_name;
    Raymon111111
        7
    Raymon111111  
       2019-09-30 10:40:25 +08:00
    加上 user_id, action_type, time 的联合索引之后

    直接查就行了, limit 1 很快的
    misaka19000
        8
    misaka19000  
       2019-09-30 10:41:04 +08:00
    每天凌晨算一次不就行了
    seaguest
        9
    seaguest  
       2019-09-30 10:41:22 +08:00
    直接代码去实现吧,把用户都分页查出来,然后查每个用户的第一条,控制好并发,也很快的。
    misaka19000
        10
    misaka19000  
       2019-09-30 10:41:49 +08:00
    这种数据都是确定的,每天针对最新数据算一次就可以了,感觉没啥难度
    ccoming
        11
    ccoming  
       2019-09-30 10:56:12 +08:00
    是“首次”,不是最新?
    LoremIpSum
        12
    LoremIpSum  
    OP
       2019-09-30 11:12:02 +08:00
    @ccoming 首次!
    jieee
        13
    jieee  
       2019-09-30 11:12:49 +08:00
    单独维护一张表
    tanszhe
        14
    tanszhe  
       2019-09-30 11:15:10 +08:00
    就用 3 楼的写法 ,
    把首次 xxx 的数据存到时序数据库
    什么都不用优化 百亿也很快
    xio
        15
    xio  
       2019-09-30 11:39:32 +08:00
    postgres left join lateral
    opengps
        16
    opengps  
       2019-09-30 11:40:26 +08:00
    看到这类帖子我就想总结下: https://www.opengps.cn/Blog/View.aspx?id=470&from=v2ex
    msg7086
        17
    msg7086  
       2019-09-30 12:43:12 +08:00
    首次多简单,直接写代码扫全表啊,数据放在 redis 之类的地方。程序每次记录扫完的数据,从头开始一页一页扫。(比如每页 10 万条记录。)扫到以后去 redis 检查是否首次,是的话写下时间,不是的话跳过。
    应该很快的。
    passerbytiny
        18
    passerbytiny  
       2019-09-30 13:35:59 +08:00
    最省心(但最废功夫)的办法是,搞数据仓库或 BI。最省功夫(但要一直重复造轮子)的方法是,写一个专门的程序,把数据从基础表抽取到中间表。最不可能的方式是,写一个超牛逼的 SQL 查出来。
    Soar360
        19
    Soar360  
       2019-09-30 15:40:18 +08:00
    按行去处理咯。
    vmskipper
        20
    vmskipper  
       2019-09-30 15:43:05 +08:00
    这个好像微博的面试题。。。。
    dog82
        21
    dog82  
       2019-09-30 15:44:53 +08:00
    这种需求不难,把“首次 xxx”记录单独记录一张表就行
    veike
        22
    veike  
       2019-09-30 16:04:41 +08:00 via Android
    注册之后首次吗?接近百万用户也不多啊,加个用户附表
    gamexg
        23
    gamexg  
       2019-09-30 16:11:37 +08:00
    联合索引,
    查询没什么问题,就是如果各种索引太多会影响插入速度。
    pinews
        24
    pinews  
       2019-09-30 22:14:20 +08:00
    16M 内存的服务器和 16G 的服务器速度的确不一样,上云数据库试试,没有不合适。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3382 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:46 · PVG 08:46 · LAX 16:46 · JFK 19:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.