来了几个比较不好处理的需求: 统计用户首次 XXX 的时间,XXX 代表用户行为,可以是评论,发帖,点赞等,XXX 表的数据上亿,用户表也接近百万,直接用 SQL 去查肯定不是很合适,如果要把每个用户首次 XXX 的数据拿出来的话,大概怎么样来跑数据比较合适?
1
liprais 2019-09-30 10:26:55 +08:00
为啥直接写 sql 不合适?
|
2
alamaya 2019-09-30 10:30:27 +08:00
没戏,拆表,把用户行为细分,存量数据迁移,只记录最新行为时间
|
3
LoremIpSum OP |
4
encro 2019-09-30 10:33:49 +08:00
stat_by_day:
date, action, value |
5
sadfQED2 2019-09-30 10:34:11 +08:00
分表 or 加缓存
你用 uid 分表不就完事了吗 |
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;
|
7
Raymon111111 2019-09-30 10:40:25 +08:00
加上 user_id, action_type, time 的联合索引之后
直接查就行了, limit 1 很快的 |
8
misaka19000 2019-09-30 10:41:04 +08:00
每天凌晨算一次不就行了
|
9
seaguest 2019-09-30 10:41:22 +08:00
直接代码去实现吧,把用户都分页查出来,然后查每个用户的第一条,控制好并发,也很快的。
|
10
misaka19000 2019-09-30 10:41:49 +08:00
这种数据都是确定的,每天针对最新数据算一次就可以了,感觉没啥难度
|
11
ccoming 2019-09-30 10:56:12 +08:00
是“首次”,不是最新?
|
12
LoremIpSum OP @ccoming 首次!
|
13
jieee 2019-09-30 11:12:49 +08:00
单独维护一张表
|
14
tanszhe 2019-09-30 11:15:10 +08:00
就用 3 楼的写法 ,
把首次 xxx 的数据存到时序数据库 什么都不用优化 百亿也很快 |
15
xio 2019-09-30 11:39:32 +08:00
postgres left join lateral
|
16
opengps 2019-09-30 11:40:26 +08:00
看到这类帖子我就想总结下: https://www.opengps.cn/Blog/View.aspx?id=470&from=v2ex
|
17
msg7086 2019-09-30 12:43:12 +08:00
首次多简单,直接写代码扫全表啊,数据放在 redis 之类的地方。程序每次记录扫完的数据,从头开始一页一页扫。(比如每页 10 万条记录。)扫到以后去 redis 检查是否首次,是的话写下时间,不是的话跳过。
应该很快的。 |
18
passerbytiny 2019-09-30 13:35:59 +08:00
最省心(但最废功夫)的办法是,搞数据仓库或 BI。最省功夫(但要一直重复造轮子)的方法是,写一个专门的程序,把数据从基础表抽取到中间表。最不可能的方式是,写一个超牛逼的 SQL 查出来。
|
19
Soar360 2019-09-30 15:40:18 +08:00
按行去处理咯。
|
20
vmskipper 2019-09-30 15:43:05 +08:00
这个好像微博的面试题。。。。
|
21
dog82 2019-09-30 15:44:53 +08:00
这种需求不难,把“首次 xxx”记录单独记录一张表就行
|
22
veike 2019-09-30 16:04:41 +08:00 via Android
注册之后首次吗?接近百万用户也不多啊,加个用户附表
|
23
gamexg 2019-09-30 16:11:37 +08:00
联合索引,
查询没什么问题,就是如果各种索引太多会影响插入速度。 |
24
pinews 2019-09-30 22:14:20 +08:00
16M 内存的服务器和 16G 的服务器速度的确不一样,上云数据库试试,没有不合适。
|