V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dbfox
V2EX  ›  程序员

用户中心,关注用户动态的功能,数据库结构是如何设计的?

  •  
  •   dbfox · 2015-07-19 18:29:16 +08:00 · 9863 次点击
    这是一个创建于 3414 天前的主题,其中的信息可能已经有所发展或是发生改变。
    按照常规的设计涉及到 几个表

    [user] 用户信息表
    id (int)
    name

    [user_msg] 用户发表动态的表
    uid (int)
    date
    content



    [user_care] 用户关注表
    userid (int)
    useridb (int)


    如果我关注了1000个用户
    那么用户中心首页把这1000个用户的动态,按照时间顺序展现出来前100 条,可以分页

    那么sql 就是

    select top 100 * from [user_msg] where uid in(select useridb from [user_care] where userid=我的用户id) order by date desc;


    这样用 in 性能是不是非常糟糕??

    有没有更好的办法?如何设计呢?
    第 1 条附言  ·  2015-09-08 11:52:06 +08:00
    这么多人关注,
    分享下我现在总结的表结构:

    理论上 feed_last_1 读取最频繁,所以数据里应该尽可能限制到最小

    [user_care] 用户关注表

    sid 被关注者 id
    uid 用户 id
    date 日期



    [feed_last_1] 用户动态表 1 (根据需求 保存 1-3 天内的数据)

    uid 用户 id
    date 日期
    des 动态

    [feed_last_2] 用户动态表 2 (根据需求 保存 7 天内的数据 排除了[feed_last_1]中的)

    uid 用户 id
    date 日期
    des 动态

    [feed_last_3] 用户动态表 3 (根据需求 保存 30 天内的数据 排除了[feed_last_1]和[feed_last_2]中的)

    uid 用户 id
    date 日期
    des 动态

    [feed_last_other] 用户动态表其他 (保存排除,feed_last_1,feed_last_2,feed_last_3 )

    uid 用户 id
    date 日期
    des 动态

    [feed] (所有的用户动态)

    uid 用户 id
    date 日期
    des 动态
    第 2 条附言  ·  2015-12-18 11:01:10 +08:00

    看了下 oschina 动态的设计

    http://www.oschina.net/question/12_70587?sort=default&p=1#answers

    总结如下:

    [osc_opt_logs]      用户动态表
            id      动态 id
            user    用户 id
            msg     动态
    
        [osc_friends]       用户粉丝表
    
            user    用户 id
            friend  用户粉丝 id
    

    主要是 sql 的写法:没有用 in 查询

    SELECT l.* FROM 
    
            osc_opt_logs l,
    
            osc_friends f 
    
        WHERE 
    
            l.user=f.friend AND 
    
            f.user = ? 
    
        ORDER BY l.id DESC
    
    14 条回复    2015-07-19 19:55:42 +08:00
    yuziyu
        1
    yuziyu  
       2015-07-19 18:38:53 +08:00   ❤️ 1
    用推模式写扩散,产生动态的时候,把他的动态fanout到他的听众的feed表去。读的时候直接读feed表。
    dbfox
        2
    dbfox  
    OP
       2015-07-19 18:45:00 +08:00
    @yuziyu 好主意,代码上要下功夫了
    ipconfiger
        3
    ipconfiger  
       2015-07-19 19:15:54 +08:00   ❤️ 1
    @yuziyu 纯粹的推模式在有粉丝超级多的明星用户的时候会遇到严重的性能瓶颈,去看看新浪微博的实现介绍啦,完整的实现是超过一定数量的粉丝的人发动态就不走推模式了
    dbfox
        4
    dbfox  
    OP
       2015-07-19 19:28:30 +08:00
    @ipconfiger 嗯,我已经算出来了,推模式的话,数据量非常非常的大,

    如果网站有10万的用户
    每个用户有100个粉丝
    每个用户每天发表10条动态

    那么一天要推的数据就是 10万 * 100 *10 = 1亿的数据量

    我去看看新浪怎么做的,ls 有现成的资料,直接发下啊
    hellokittyer
        5
    hellokittyer  
       2015-07-19 19:32:00 +08:00 via Android
    标记上一次获取的动态id,当用户登录或者在线的时候队列拉取
    bdbai
        6
    bdbai  
       2015-07-19 19:35:27 +08:00 via iPhone
    可以结合非结构化数据库,比如把动态ID推到每个粉丝的feed中,粉丝只要读feed再从动态表中拉取内容即可。
    dbfox
        7
    dbfox  
    OP
       2015-07-19 19:37:51 +08:00
    @hellokittyer
    不行啊,要把关注用户的动态都列出来
    hahasong
        8
    hahasong  
       2015-07-19 19:43:29 +08:00
    这个问题很经典,坐看高人解决
    hellokittyer
        9
    hellokittyer  
       2015-07-19 19:45:07 +08:00 via Android
    怎么会不行呢,这样做你还可以剔除不活跃用户。
    dbfox
        10
    dbfox  
    OP
       2015-07-19 19:48:16 +08:00   ❤️ 1
    @bdbai 嗯,目前我想的是这样,楼上有也这样说
    但是数据量很大,单用户动态多的话,粉丝多的话,用户总数多的话,每天的推送量估计要排队好久
    网站整体性能估计还是不行,只能堆服务器



    1、当一个用户产生一条内容的时候,存储在数据库一份内容,同时发送到另一台服务器专门处理动态
    2、另一台服务器接收到一条动态,根据这条动态的用户信息,找出该用户的粉丝列表

    3、
    用户id 1-10000 的用户订阅动态 放一台服务器
    用户id 10001-20000 的用户订阅动态 放一台服务器
    用户id 20001-30000 的用户订阅动态 放一台服务器
    用户id 30001-40000 的用户订阅动态 放一台服务器
    .................

    这样就可以动态的扩展服务器

    根据粉丝列表的id ,分别把这条动态发送给不同的服务器去处理存储


    4、某用户中心的用户看动态的时候,实际上访问额不同的服务器
    hellokittyer
        11
    hellokittyer  
       2015-07-19 19:48:58 +08:00 via Android
    首先每个用户都要有maxmsgid
    其次,登录或主动拉取时,对比maxmsgid跟动态表里的最大id(也可以缓存减少一次查询)
    最后查询出maxmsgid跟动态表最大id之间关注用户的动态,插入关系表,同时更新maxmsgid(这里可分批次)
    手机码字,看懂酒行。
    dbfox
        13
    dbfox  
    OP
       2015-07-19 19:52:29 +08:00
    @hellokittyer
    懂你的意思,比如我订阅了100个用户,我要看到这100个用户动态的汇总,然后是按照时间倒叙排列的

    需要 我订阅这个100个用户记录上次我看到的最后的他们的分别最后的id

    但是我需要进行100次拉取,这样就 over了,而且排序是个问题
    hellokittyer
        14
    hellokittyer  
       2015-07-19 19:55:42 +08:00 via Android
    累觉不爱,好好研究吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1000 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:47 · PVG 06:47 · LAX 14:47 · JFK 17:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.