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

三人脉关系怎么存储比较合理呢

  •  
  •   ohmyga · 2015-09-21 08:01:04 +08:00 via iPhone · 4482 次点击
    这是一个创建于 3335 天前的主题,其中的信息可能已经有所发展或是发生改变。
    A 推荐 B 注册 B 就是 A 的一级人脉

    B 推荐 C 注册 C 就是 B 的一级人脉, C 是 A 的二级人脉

    C 推荐 D 注册 D 就是 C 的一级人脉, D 是 B 的二级人脉, D 是 A 的三级人脉

    每注册一人数据库记录该人上级关系可行吗

    D-C-1
    D-B-2
    D-A-3

    C-B-1
    C-A-2

    B-A-1
    23 条回复    2017-08-02 01:08:23 +08:00
    ljbha007
        1
    ljbha007  
       2015-09-21 08:37:11 +08:00
    你那种也可以 但是查询会很不方便 有几层人脉关系就要查询几次

    如果楼主的业务逻辑是树状关系 可以这样解决:
    http://falsinsoft.blogspot.com/2013/01/tree-in-sql-database-nested-set-model.html


    如果楼主的关系网络是图状关系 那么最好使用专业的图数据库 graph database

    比如说一个: http://neo4j.com
    http://thinkaurelius.github.io/titan/

    这个 neo4j 我粗略看了一下 跟 sql 很类似 应该可以做到比较容易的迁移
    dong3580
        2
    dong3580  
       2015-09-21 08:50:11 +08:00 via Android
    多少层无关紧要,都是父子而已,所谓的关系型数据库就是这个道理!
    lavadore
        3
    lavadore  
       2015-09-21 08:52:31 +08:00
    只记录上级就可以了,多少层看你查询的时候怎么查了
    ohmyga
        4
    ohmyga  
    OP
       2015-09-21 09:01:32 +08:00
    @lavadore 用户数量大概 10W, 只查用户的 特别级别的人脉,不会一起查询用户的所有级别人脉.如果查询用户一级人脉还好,如果要查询用户的所有的 2 级 或 3 级人脉.只记录上一级是不是渣了些.
    quericy
        5
    quericy  
       2015-09-21 09:19:44 +08:00
    羡慕 LZ,我们产品搞的是 5 级人脉....还要查所有上级和下级 直接是个 N 叉树的林了
    ohmyga
        6
    ohmyga  
    OP
       2015-09-21 09:44:43 +08:00
    @quericy 哈哈 5 级交叉 压力够大啊
    ljbha007
        7
    ljbha007  
       2015-09-21 09:48:57 +08:00
    @ohmyga
    如果知识树状关系用我发的那种办法查询子树效率很高 也很容易理解 大概是这个样子

    SELECT * FROM users WHERE users.left > myleft and users.right < myright;
    lavadore
        8
    lavadore  
       2015-09-21 10:02:32 +08:00
    @ohmyga 一级直接记录了,不用查啊, 2 , 3 级 join 自己就可以了,考虑效率的话可以提取到另外一张表中。个人感觉比都塞在一张表中要好
    mulog
        9
    mulog  
       2015-09-21 10:18:20 +08:00
    Neo4j
    我只是随便说说^^
    500miles
        10
    500miles  
       2015-09-21 10:20:29 +08:00
    那种 left right 的预先排序方式 , 明显不太适合业务场景, 不停的有人注册, 真要命...

    parent_id 的方式, 查询时候太费劲, 你后面可能大量统计

    所以 楼主提出的详细记录就挺好的啊....

    另外 path 的方式 我觉得也非常合适. 简洁明快, 也容易搞缓存.
    liangqing
        11
    liangqing  
       2015-09-21 10:27:47 +08:00
    最大多少级?如果这个级数不大的话,比如 10 ,放 10 个 Key 就行了阿。。简单粗暴。
    ohmyga
        12
    ohmyga  
    OP
       2015-09-21 10:46:15 +08:00
    @liangqing 就三级
    wintersun
        13
    wintersun  
       2015-09-21 10:56:57 +08:00
    @ohmyga 同意 @ljbha007 的建议,关系数据库保存基本信息和一度关系, Graph Database 保存多维度关系
    目前我也在研究 Neo4j ,虽然有评测说其读写性能远低于 MongoDB ,更不用说 MySQL 了,但是我相信其编程模型有利于简化代码,并且在实际应用场景中效率未必就关系数据库差……
    Yanel
        14
    Yanel  
       2015-09-21 11:27:42 +08:00
    这样只记录了上级的数据库查询,一个拥有几千下级的用户查询就会非常费劲啦
    thinkmore
        15
    thinkmore  
       2015-09-21 11:41:24 +08:00
    @ljbha007 网址打不开
    liangqing
        16
    liangqing  
       2015-09-21 11:41:26 +08:00
    @wintersun 我们用过 Neo4j , 13 万数据,存储公司的员工关系,查询速度惨不忍睹, 1 个页面 50 几秒才出来。就是遍历一边也不要这么久阿。后来改用 Elasticsearch 了,秒出。
    sobigfish
        17
    sobigfish  
       2015-09-21 12:10:33 +08:00
    @wintersun 效率这么低啊?
    他们自己的服务器例子
    http://console.neo4j.org/

    Query took 295 ms and returned 4 rows.
    Query took 993 ms and returned 4 rows.

    后来页面里再 run 倒是降到 2ms 之类的(缓存了?)
    takato
        18
    takato  
       2015-09-21 12:53:27 +08:00
    @liangqing - -做了一个怎样的查询?
    liangqing
        19
    liangqing  
       2015-09-21 13:24:11 +08:00
    @takato 不止一个查询,有大量连接操作。
    ljbha007
        20
    ljbha007  
       2015-09-21 13:41:11 +08:00
    @500miles
    对 我没考虑到用户表是个经常插入的表这个问题 这样的话用 left 和 right 的效率还不如有多少层查询多少次
    BobLuo
        21
    BobLuo  
       2015-09-21 13:45:58 +08:00
    可以考虑用图形数据库来做存储
    raincious
        22
    raincious  
       2015-09-21 14:11:37 +08:00
    可能我没理解这个问题。但是这样的静态数据不能用缓存来减少查询么?

    比如建立一张表,`user_relation_registerinvitations`,结构就像:

    (Primary Key ),
    userID int,
    inviters char

    然后`inviters`里存这个用户的上一级邀请者数组,比如用户 D 的邀请者们是:用户 A,用户 B,用户 C

    当有用户 E 通过这个用户 D 的邀请注册的时候,就将这个用户 D 的`inviters`数组读出来放到一个变量里, Shift 出最前的那个用户 A , Push 进用户 D 。然后用变量里的那个新的`inviters`数组为用户 E 建立`人脉表`的数据项,表示他们分别是用户 E 的第 X 级人脉(记得倒过来)。

    最后,为用户 E 在`user_relation_registerinvitations`里新建一个项,数据是

    `userID` = 用户 E 的 ID
    `inviters` = 用户 B,用户 C,用户 D (新的`inviters`数组)

    这样当这个用户也要请其他用户注册的时候,就可以延续了。
    HanSonJ
        23
    HanSonJ  
       2017-08-02 01:08:23 +08:00
    @raincious #22 这样设计的缺点在于不利于查询,假若要查询 用户 C 下面的用户,总不能用 like 吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1288 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:26 · PVG 07:26 · LAX 15:26 · JFK 18:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.