权限表设计的step by step

权限表设计的step by step

今天和同事Sinclair讨论一个权限表方面的设计,过程很有意思,DBA 不能只把精力放到数据库技术,更多的是如何让数据库的技术和设计贴近应用,只有有人用的,好用的数据库和设计才有存在的意义。

大致意思是这样的,这里隐去各种商务和公司的信息,只谈表如何设计,所以就不交代前因后果了。原来的系统是没有权限的设计,只有一个权限。现在需要加上权限给每个登录的用户,原先的USER 表已经不小了(列数)。

后面要给每个用户添加权限,下面就顺着我们讨论的路径来从原始社会到现代社会 STEP BY STEP.

1 在原来的表上添加字段,首先这个方法时最快,最省力(脑力)的方法,我直接在原来的表上添加这个账号的权限,例如 ADMIN, SALES, CHECKER 等等,那直接读出这个权限不就OK 了,然后分配相关的权限。

否定: 原来的表已经列数很多了,而且这个表应该是在某个时间段会集中访问,属于HOT 表,那BLOCKED , 死锁,那还不在某个时间段成为家常便饭,投诉估计会刚刚的,一个表的好处如果表简单,访问自然快,如果一个表已经承载了,验证,判断,提取,更新,插入,并且在一个时间段会并发的发生,这样的设计可不怎么美好。  方案 PASS

2  新加一个权限表,这点是肯定的,不会再变,会添加一个权限表,通过和USER表之间的某个唯一值的关系,来和权限表进行一个关联,而权限表的设计才刚开始。

     2.1  每个权限一个列,有几个权限就几个列,来一个权限分类就加一列,这样的设计是很正常的思维,(并且可以看看SQL SERVER 内部的权限表就是这么设计的),每一列值存储 布尔值, 1 OR  0 , 程序来判断最后获得一个权限的值。

权限表设计的step by step

缺陷:这样设计看似不错,问题是权限可能会根据需求变动,虽然不至于经常添加列,但是DDL 在数据库中因为一个已经定义好的业务去变动,这显然不是一个好的设计,并且程序需要挨个的去和数据表每一个列来去互动,这效率也是够低的。 

PASS

2.2  和程序变动来比较,数据表的设计以不变应万变才是更好的设计方式,这里提出,下面的设计,乍看怎么回事,难道就一种权限吗?

权限表设计的step by step

NO ,我们不在字段的数量上想办法,我们可以在字段的存储的内容上想办法,表越小,速度越快,获取信息交互的次数越少,表的BLOCKED , DEAD LOCK 越小。 那关键就在于权限这个字段的设计怎么来搞。

  2.2.1   存储数字来解决,例如我们有一个权限对应表,(仅仅用来说明数字和权限的关系),1 代表 ADMIN  2 代表 SALES 3代表 CHECKER 

那我们的权限列存储数字就OK 了,通过数字在程序中的转换,直接转换成权限,又快又好。

NO,经过讨论,这样的设计有一个可能存在的问题,如果一个人可能有两个权限,他既是SALES 又是 CHECKER,如何 2+3 吗 怎么表达,如果已经有5 了例如 5 号是 credit呢 ,这样设计扩展性有问题

PASS

2.2.2  用二进制来进行表达,SQL SERVER 中有一个 BINARY 的方式来表达数值,每个位数代表一个权限,我们直接用最小的存储来将复杂的权限用二进制来表达,多少权限变化将在数字 1 和 0 之间进行化解。敌动我不动,我也不用动,字段一个就够用了。

权限表设计的step by step

NO  这样的设计程序需要一个转换,通过转换来变换权限,转换+判断,有没有更省事的方法。

此方法 PASS

2.2.3 用 INT 类型存储,在判断每一位的值,INT 可以表达 2的21次方 -1 位数是够用了,但好像还是差点什么分歧点从这里开始了

2.2.4 用 VARCHAR 来表达,用VARCHAR (20)来表达,还是存储 101010101 来表达权限通过 1 0 以及位置来辨别用户的权限。

这里 2.2.3 和 2.2.4 的矛盾在于处理和存储,其实两种都OK ,但VARCHAR(20) = 3 * 20 BYTE 的存储, 而 INT 是 4 个字节,自然越小的字符占用会提升处理的速度。

最后作为目前我们能考虑到的极致,还是选用了 2.2.3 的方法,通过程序来一次提取数字,剩下的是在程序里面做判断,进行位与计算,得出相关的权限。

有的时候,差不多 和 更好,就差一步。

权限表设计的step by step