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

队伍里的小伙子这样设计表,应该怎么评价

  •  1
     
  •   5sheep · 60 天前 · 10538 次点击
    这是一个创建于 60 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目里有几个多对多关系,需要表达到关系数据库。

    比如:用户 角色 权限; 用户与角色是多对多关系;角色与权限是多对多关系;

    一般人会分别创建 [用户角色表]、[角色权限表],来存储多对多关系,这个没啥好说的。

    现在队伍里一个小伙子嫌麻烦,就创建了一张 [数据关系表],大致字段有:[第一个 id],[第二个 id],[表名]。

    大家分析下,这种做法,要如何评价

    第 1 条附言  ·  60 天前
    这个小伙子建了四个模型:用户、角色、权限、数据关系。

    我是兼着负责这个项目的技术的,过来时项目已经开发了一段时间了
    ,小伙子写的是整个平台的基础功能,我很想让小伙子按着常规方法来做

    但是小伙不直接归我管,只能讲道理,但是又没有必杀的理由

    毕竟这样做功能也能正常跑,给领导演示肯定没问题

    之类的问题很多,小伙子的台词是“你不了解,就别瞎说”。
    无言反驳,我也无法去证明我是不是了解。

    很是苦恼啊。
    106 条回复    2021-09-02 21:55:41 +08:00
    1  2  
    ScotGu
        1
    ScotGu   60 天前
    如果一张表就能搞定这个项目,那岂不是应该献上膝盖?
    securityCoding
        2
    securityCoding   60 天前
    瞎搞
    heyjei
        3
    heyjei   60 天前
    多对多的多态关系,如果他能够在 ORM 里面把这种关系配出来,就这样呗。配不出来就老老实实的多建几张表
    zjj19950716
        4
    zjj19950716   60 天前
    让他弄呗 看能玩出什么花样
    buliugu
        5
    buliugu   60 天前
    可以命名成数据爆炸表(逃
    sy20030260
        6
    sy20030260   60 天前
    这种是典型的反规范建模设计,本身是没错的,得看具体的业务场景。
    但是 [用户 角色 权限] 这种系统设计,本来就是典型的规范建模,具体到数据库设计又变成反规范的,就有点奇怪了~
    levelworm
        7
    levelworm   60 天前 via Android   ❤️ 2
    我擦表中表啊!
    ctrlaltdeletel
        8
    ctrlaltdeletel   60 天前   ❤️ 1
    最终这个模块变成了个图数据系统 XD
    bk201
        9
    bk201   60 天前
    就是将关系类的数据统一放在一个表里了,数据量不大的情况下感觉也没什么问题
    yeeli
        10
    yeeli   60 天前
    数据不大都无所谓, 如果你以后是要搽屁股的负责人就提早改,很多时候项目和员工都撑不到爆的那一天
    shanghai1943
        11
    shanghai1943   60 天前
    一表多用了。不合理的设计。
    rabbbit
        12
    rabbbit   60 天前   ❤️ 2
    没太看懂,是指他存了这么个表吗?

    id1 | id2 | 表名
    角色 id1| 权限 id1 | 用户权限表名
    角色 id1| 权限 id2 | 用户权限表名
    角色 id2| 权限 id1 | 用户权限表名
    权限 id1| 角色 id1 | 用户角色表名
    k9982874
        13
    k9982874   60 天前
    直接甩他直属领导脸上,问就你招的这么个玩愣?
    l00t
        14
    l00t   59 天前
    不知道你在说什么东西,什么第一个 ID 第二个 ID 表名,人家的字段没实际业务含义的吗?
    wolfie
        15
    wolfie   59 天前
    又是当时没怼过,越想越气。
    user_role 、role_operation 这类设计较通用的表强行复杂化。
    增加他人理解成本,并没有降低什么工作量,大数据量速度还差。
    lower
        16
    lower   59 天前
    @l00t 看 12 楼的说明😂
    cocong
        17
    cocong   59 天前
    不是你负责的就不用管,你也管不了,瞎操心。
    如果出问题了你要跟着背锅的,那就把问题反映给上级,把锅甩出去。
    总的来说,如果数据量小,版本迭代慢,那怎么搞都问题。如果数据量大,或者需求经常变动,那后面加班只会越来越多。
    fgwmlhdkkkw
        18
    fgwmlhdkkkw   59 天前   ❤️ 1
    我觉得可以优化一下,表名改为数字,挺好的吧……
    xiao109
        19
    xiao109   59 天前
    @l00t 应该就是把几个关联关系表合并成一张表,加个 type 字段区分一下。
    comoyi
        20
    comoyi   59 天前
    5 张表,用户,角色,用户-角色关系,权限,角色-权限关系
    qping
        21
    qping   59 天前
    貌似用着也没有什么问题,数据量一般也不会大

    就是感觉怪怪的,能用但是不够漂亮。
    young1lin
        22
    young1lin   59 天前 via Android
    反范式设计,开发一时爽,维护火葬场。除非这个项目一定是他维护,不然让他改
    young1lin
        23
    young1lin   59 天前 via Android   ❤️ 1
    这个就是典型的 RBAC0 设计思路的表,你可以把更详细的 RBAC1, RBACA2, RBAC3 讲给他,还有 ACL,ABAC, PBAC 讲给他,让他去查。还有 Shiro/Spring Security 怎么实现的,最好是 Shiro 比较简单。再对比下他的设计,再让他说说你懂不懂。
    avastms
        24
    avastms   59 天前   ❤️ 1
    你不了解,就别瞎说

    邻接表,这是图查询的基石,只要数据库稍微支持一下图查询,这个结构能提供的比你那个捉鸡所谓关系模型多得多
    soulzz
        25
    soulzz   59 天前
    那还不如全用 mongodb 用户权限也和用户基本资料放一起,直接定义各个接口的权限
    R18
        26
    R18   59 天前
    你让他严格按照 BCNF 来就行了。
    falcon05
        27
    falcon05   59 天前 via iPhone   ❤️ 17
    楼主这表达能力让我想了半天,什么 id1,id2 的,说服力估计也不行❌
    jtwor
        28
    jtwor   59 天前
    数据库三范式。。。 那这样关联岂不是要带上 表名 条件。。
    YUyu101
        29
    YUyu101   59 天前
    小伙子这样做就代表他把这些关系当成一个实体了,如果这些表的关系真的只有关系那没什么好说的,万一以后要给每种关系加各自属性,那他是准备搞父子表还是让多出来的字段空着,其实怎么设计都行,只要能评估好未来的工作量。
    johnsonqrr
        30
    johnsonqrr   59 天前   ❤️ 2
    还能怎么办,上网发个贴呗
    mosakashaka
        31
    mosakashaka   59 天前
    索引搞好效率不会有问题。
    Frauhling
        32
    Frauhling   59 天前   ❤️ 1
    @fgwmlhdkkkw 这个表名改为数字的主意听着就很好 XD 就是不知道是楼主先跑路还是这个小伙子先跑路
    zxcslove
        33
    zxcslove   59 天前
    这样最大的问题是,不同的关联关系如果有不同的数据就悲剧了,只是做关联用你是杠不过他的。
    5sheep
        34
    5sheep   59 天前
    @rabbbit 是这样存的
    真实建表语句如下:
    CREATE TABLE [dbo].[DataConnect]( --数据关系表,可存一切多对多关系
    [Id] [uniqueidentifier] NOT NULL,
    [SourceCode] [nvarchar](100) NULL, --存表名
    [FirstId] [uniqueidentifier] NULL, --第一个 id
    [SecondId] [uniqueidentifier] NULL, --第二个 id
    [ThirdId] [uniqueidentifier] NULL, --预留字段
    ... 其它预留字段
    DavidDee
        35
    DavidDee   59 天前
    @5sheep FirstId 、SencodId 、ThirdId,我更疑惑了。?这些 id 存的是什么?
    5sheep
        36
    5sheep   59 天前
    @DavidDee 看 12 楼的例子
    5sheep
        37
    5sheep   59 天前
    12 楼的最后一行不准确,我修改下
    @DavidDee

    id1 | id2 | 表名
    角色 id1| 权限 id1 | 用户权限表名
    角色 id1| 权限 id2 | 用户权限表名
    角色 id2| 权限 id1 | 用户权限表名
    用户 id1| 角色 id1 | 用户角色表名
    用户 id1| 角色 id2 | 用户角色表名
    code4you
        38
    code4you   59 天前
    只要小伙子 能搞定 能跑就行
    baoshijiagong
        39
    baoshijiagong   59 天前
    sql 里面,表名如果写错,不会报错,还会以为没有数据。不好排查原因。
    DavidDee
        40
    DavidDee   59 天前
    @5sheep
    所以就是他将本来该分为两个多对多的关系表,直接使用了一个表设计,所以 id1,id2 是字段是无法确定存放的是什么内容。
    如果表名 == 用户角色表名,那么 id1 就是用户 id,id2 就是角色 id ;
    如果表名 == 用户权限表名,那么 id1 就是角色 id,id2 就是权限 id 。
    pws22
        41
    pws22   59 天前
    说实话,如果没有一些关联特殊要求,其实设计一个大表做关联没什么毛病,就是直观看上去不好理解,但是程序逻辑能弄清就行,但是如果关联上有一些额外的字段,说不定过了一段时间再看,都会忘记了当初的设计条件了,看代码也会一脸懵,咋回事,都是反复调用这个大关联表来做操作..不能图一时轻松,还有考虑后期的维护成本和其他后来人的接受程度,选择一个大家都能比较好理解的做法. ps 如果是我组成员做出这样的,限期修改吧.
    murmur
        42
    murmur   59 天前
    好家伙,表名直接写到数据里么
    c6h6benzene
        43
    c6h6benzene   59 天前 via iPhone   ❤️ 2
    人和程序有一个能跑就行 /doge
    baoshijiagong
        44
    baoshijiagong   59 天前
    维护性很烂,也没什么好处,比如联表时要写 data_relationship.table_name='user_role' and data_relationship.firstId = user.id, 实际上不存在 user_role 表,所以字段名也让人不明所以,用正常的方式是 user.id = user_role.user_id, 简洁明了。对于使用了某些框架的系统,更是阻碍。
    baoshijiagong
        45
    baoshijiagong   59 天前
    有这种表的存在,连数据库表的模型图都不能直观画出来。
    kingfalse
        46
    kingfalse   59 天前
    这哥们把 mysql 当 mongo 用了吗这是
    vone
        47
    vone   59 天前
    笑死,那可以把所有表都合并成一个,极为方便。
    way2create
        48
    way2create   59 天前
    感觉这样更复杂啊其实
    way2create
        49
    way2create   59 天前
    感觉你脸皮没他厚 怼不过他
    rationa1cuzz
        50
    rationa1cuzz   59 天前
    我接受这个项目,小伙是这么建表的:[角色权限 1 表]、[角色权限 2 表]、[角色权限 3 表]、[角色权限 4 表]。。。。
    cnrting
        51
    cnrting   59 天前 via iPhone
    这不是你该操心的事
    ttyn
        52
    ttyn   59 天前
    公司流程问题,这样的设计也并非不可以,要结合具体的项目来看,
    稍微正规点的应该有个“设计 -> 评审 ”流程
    评审通过,出问题大家一起背锅,
    评审不通过,打回去修改
    fml87
        53
    fml87   59 天前
    典型的眼高手低,场景又不复杂,这样搞只是白白增加维护成本
    intmax2147483647
        54
    intmax2147483647   59 天前
    你不了解,就别瞎说。🤣
    11232as
        55
    11232as   59 天前
    A 多对多 B,B 多对多 C
    | B_id | A/C id | A/C 表名|
    | --- | --- | --- |
    | ... | ... | ... |
    虽然有点怪但也没啥问题...
    cszchen
        56
    cszchen   59 天前 via iPhone
    没看出来哪儿方便了,工作量不仅不会变小,可能还会变大,如果有可能就让他做简单的 curd,或者直接开掉
    redford42
        57
    redford42   59 天前
    表设计还是评审一下吧
    JoeBreeze
        58
    JoeBreeze   59 天前
    团队合作还是需要一些规范的, 他喜欢这样做, 然后其他人也大部分都认同, 打不过就加入吧, 后面有锅给他背就好了
    egfegdfr
        59
    egfegdfr   59 天前
    这么搞,在做删除、新增操作的时候,不容易产生死锁吗? 虽能说 可以通过加索引、或者是分布式锁控制,但是这个设计好几个业务逻辑,感觉这么设计的优点是小于缺点的
    Carlgao
        60
    Carlgao   59 天前
    在多对多中间表里面加表名类型区分,可以减少中间表的数量,这属于常规操作吧。
    drinke9
        61
    drinke9   59 天前
    这种设计模式,laravel 框架中的一个权限包就是这种结构,`laravel-permission`
    qwe520liao
        62
    qwe520liao   59 天前
    看场景吧,一般角色对权限的是配置数据,数据量不大可以做缓存,更新的情况也比较少。甚至可以把角色对权限的这个关系直接通过配置文件存储起来,都不用存数据库。

    而用户对角色的这部分数据是动态数据表,适合放到数据库中。话说回来,量变导致质变,不同的量级有不同的做法,条条大路通罗马。有规范的按照规范执行,没有的话按照简单的来做就行了,在没有规范的前提下就不要苛求太多。
    0o0o0o0
        63
    0o0o0o0   59 天前
    关键是这逻辑是怎么想出来的,正常人第一次设计都会去网上搜索一下经验或者规范吧,所以说这是自己发明的神奇设计方法吗哈哈哈
    charseer
        64
    charseer   59 天前
    一些参数表这样设计没啥问题,很好用的
    Muyiafan
        65
    Muyiafan   59 天前
    表中表中表中表中表中表
    superrichman
        66
    superrichman   59 天前
    @baoshijiagong 怕模型图最后画出来是个刺猬 /doge
    Guidoo
        67
    Guidoo   59 天前
    好家伙 套娃 表中表中表中表中表中表中表中表中
    aliveyang
        68
    aliveyang   59 天前
    他以为动态了,其实是乱搞
    Leviathann
        69
    Leviathann   59 天前 via iPhone
    元编程是吧
    conanforever22
        70
    conanforever22   59 天前
    他可能是觉得项目中有很多这种“类似”的关系, 不想建那么多表

    感觉像我们平时分析某个业务场景, 经过思考,抽象出了一个精炼“通用”的结构;可能真的通用,能应对未来各种变化;也可能忽视了这些变化,然后各种 if...else...特殊处理

    看表结构里他还建了很多预留字段,可能是考虑到某些关系可能会附加一些属性,如果能解决问题也没有性能问题,其他同事也能看懂没意见,管他呢...
    guisheng
        71
    guisheng   59 天前 via iPhone
    个人觉得,这种做法在解决问题上是没有什么好说的。但是在可维护性上和可扩展性上 直接一巴掌拍死。
    guanhui07
        72
    guanhui07   59 天前 via Android
    不合理
    pepesii
        73
    pepesii   59 天前
    这有点像 CASBIN 的 RBAC 模型呢
    twing37
        74
    twing37   59 天前
    第一感觉是 casbin 的模型
    konakona
        75
    konakona   59 天前
    这个表中表的设计必须是 1:1 的关系就是合理可用且没有诟病的,我指的是:

    Aid | Bid | model | remark
    1 | 2 | string | ...

    比如 Aid 的 field name 可以是 permission_id,Bid 的 field name 可以是 model_id 或者 role_id,model 的 field name 可以是某种 type (比如 model_type 或者任何能够代表操作类的 field name 去说明它)

    这个表不能复杂,最多就这么 3-4 个主要子段,因为它的定位应该是一个“中间表”。但……这也只是中间表,如果要在一个表里完成复杂的蛛网一般的交织,后续维护和理解成本(主要体现在陈长的代码里)会比较麻烦,不易维护和改造。
    konakona
        76
    konakona   59 天前
    我看了看楼主的 append,这个小伙的做法好像没什么问题啊- - 很常规,很 ok 。建议看下 casbin 。。。
    ericls
        77
    ericls   59 天前 via iPhone
    GenericForeignKey
    mejee
        78
    mejee   59 天前 via iPhone
    感觉是建立了一个表达通用关系的表,如果是的话,可能也是很合适的
    Casbin
        79
    Casbin   59 天前
    这是 Casbin
    ericls
        80
    ericls   59 天前
    @Casbin 你才是 Casbin
    mmdsun
        81
    mmdsun   59 天前
    还有表名称? 关系数据库 Mysql 这种要怎么查询 ?
    seakingii
        82
    seakingii   59 天前
    反直觉
    不过就这个场景来说,是能满足要求的,也能扩展应用到所有这种简单多对多的其它表.数据量不大的话性能也不是问题
    akira
        83
    akira   59 天前
    这样的优点是 少创建一个表,嗯。 应该就这个了吧
    l4ever
        84
    l4ever   59 天前
    还行啊, 没啥毛病. 我更倾向于把所有配置全写一个表里面去.

    ```
    CREATE TABLE `system_config` (
    `id` mediumint UNSIGNED NOT NULL AUTO_INCREMENT,
    `userid` char(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
    `module` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
    `section` char(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
    `key` char(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
    `value` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE INDEX `unique`(`userid`, `module`, `section`, `key`) USING BTREE
    ) ENGINE = MyISAM AUTO_INCREMENT = 2680 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    ```
    cp19890714
        85
    cp19890714   59 天前 via Android
    谁最终为该系统负责,那就听谁的。当然,还是要以理服人,举例说明该方式在未来的隐患。
    WilliamYang
        86
    WilliamYang   59 天前
    从业 6 年了,某些人总能找到说服你和他自己的理由。你不是他上级,能听就听,不听就算了
    chih758
        87
    chih758   59 天前
    不是本科毕业的?数据库的范式没学?
    entro
        88
    entro   58 天前
    真实,本公司项目某模块的表就是老板亲自用这种方式设计的#(笑)
    hst001
        89
    hst001   58 天前 via Android
    数据量稍微多点,更新的时候就知道厉害了,后面让他再去拆表,长长教训
    2i2Re2PLMaDnghL
        90
    2i2Re2PLMaDnghL   58 天前
    重新发明图数据库
    把不同表(实际上就是不同的命名空间)的 id 放在一起,需要保证表间 id 仍然唯一(实质达成命名空间合并)。
    这种情况下 MySQL 性能可能捉鸡
    TimPeake
        91
    TimPeake   58 天前
    套娃?
    wqtacc
        92
    wqtacc   58 天前
    看起来是把角色权限和用户角色写到了一个表里?那描述应该是下面这样子?

    id1 | id2 | 表名
    角色 id1| 权限 id1 | 用户权限表名 角色权限?
    角色 id1| 权限 id2 | 用户权限表名 角色权限?
    角色 id2| 权限 id1 | 用户权限表名
    用户 id1| 角色 id1 | 用户角色表名
    用户 id1| 角色 id2 | 用户角色表名
    Biwood
        93
    Biwood   58 天前
    乍一看,还以为是什么数据库层面的高度抽象,专门存储表与表之间的关系?太高级了吧
    看到“第一个 id”、“第二个 id”这里,有点懵逼了,这是用一个表解决整个系统的对应关系?有种用 0 和 1 写程序的感觉,按照这种写法,那数据库要“主键”、“外键”干嘛用
    Biwood
        94
    Biwood   58 天前
    @avastms
    我一开始也以为像是你说的邻接表,把数据之间的关系存储起来,但是你在细读一下楼主的描述跟他的回复,根本没那么高大上,他是反向操作,纯粹是把三张表之间两两排列组合,把每一条关系都存储在一个表里面。

    打个比方,就像你本来可以用 for 循环打印 10 次数据,他偏偏不用 for 循环,而是硬写了 10 次打印数据的代码。
    changdy
        95
    changdy   58 天前
    原谅我..没 get 到点. 虽然这个操作的确不教条主义... 但是我觉得 还 ok 吧....


    @l4ever 你这个就太过分了... 只是系统配置范畴的 可以.但是权限表什么的 就很不合适了.
    encro
        96
    encro   57 天前
    没有问题,
    其实 yii 框架的默认 rbac 差不多也是这么建立的。基于 NIST RBAC model,性能没有问题,且可以多级用户角色和权限继承。


    DbManager 使用 4 个数据库表存放它的数据:

    itemTable: 该表存放授权条目(译者注:即角色和权限)。默认表名为 "auth_item" 。
    itemChildTable: 该表存放授权条目的层次关系。默认表名为 "auth_item_child"。
    assignmentTable: 该表存放授权条目对用户的指派情况。默认表名为 "auth_assignment"。
    ruleTable: 该表存放规则。默认表名为 "auth_rule"。


    有个要求就是需要封装很好。
    encro
        97
    encro   57 天前
    下面是表结构,可以不考虑 rule 表

    create table `auth_rule`
    (
    `name` varchar(64) not null,
    `data` blob,
    `created_at` integer,
    `updated_at` integer,
    primary key (`name`)
    ) engine InnoDB;

    create table `auth_item`
    (
    `name` varchar(64) not null,
    `type` smallint not null,
    `description` text,
    `rule_name` varchar(64),
    `data` blob,
    `created_at` integer,
    `updated_at` integer,
    primary key (`name`),
    foreign key (`rule_name`) references `auth_rule` (`name`) on delete set null on update cascade,
    key `type` (`type`)
    ) engine InnoDB;

    create table `auth_item_child`
    (
    `parent` varchar(64) not null,
    `child` varchar(64) not null,
    primary key (`parent`, `child`),
    foreign key (`parent`) references `auth_item` (`name`) on delete cascade on update cascade,
    foreign key (`child`) references `auth_item` (`name`) on delete cascade on update cascade
    ) engine InnoDB;

    create table `auth_assignment`
    (
    `item_name` varchar(64) not null,
    `user_id` varchar(64) not null,
    `created_at` integer,
    primary key (`item_name`, `user_id`),
    foreign key (`item_name`) references `auth_item` (`name`) on delete cascade on update cascade,
    key `auth_assignment_user_id_idx` (`user_id`)
    ) engine InnoDB;
    kiracyan
        98
    kiracyan   57 天前
    其实就是把多个 map 表合在一起了吧
    wowbaby
        99
    wowbaby   57 天前
    @encro yii2 rbac 虽然方便,权限一多,随便几十条 sql
    blackshow
        100
    blackshow   56 天前
    @Casbin #79 casbin 在哪描述的数据库设计?没有找到
    1  2  
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3097 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 05:04 · PVG 13:04 · LAX 22:04 · JFK 01:04
    ♥ Do have faith in what you're doing.