关系型数据库rdbms的一个主要特征即多表,外键关联或/并加以约束。关系型数据库的优势,顾名思义,可以经过数据库自己的操做来创建、保持并维护关系,由此在集中的数据存储中,能够提供不少便利。
不过,rdbms由于将关系归入数据存储中,反而给本身形成了不少麻烦。数据建模能够很程式化的进行,这就是双刃剑,一些ORM工具很形象的将对象与表对应,而将引用与关系对应,看起来彷佛完全的解决了rdbms非对象化的问题,但其实是绕了很大的一个圈。
关系型数据库最多见的一个用法,即经过关联查询获取分散于各个表中的记录。一个问题是,什么信息须要如此大动干戈,从多张表中获取?下面以常见用户/权限系统中的模型为例,解决这个问题!
-
用户,用户自身包括用户名/密码、用户资料
-
组织结构,自身包括组织资料
-
权限,权限实际上只有一个名字,在具体体现到功能前,这个东西毫无心义
-
用户间,没有任何关系
-
组织间,存在一个上下级的联系
-
权限间,有些系统会将权限分组,但那只是一个打包的快捷方式,权限组彻底能够理解为是权限之外的东西
-
用户与组织,用户有一个或者多个组织,这在之前的系统中用rdbms实现无比麻烦,有些系统甚至只能作到一个用户同时只属于一个组织
-
用户与权限,用户同时具有多个权限,问题同上,权限组的加入让问题更加复杂化
-
组织与权限,有些系统甚至将组织和权限关联,所以不得不作出一些约定,不然其实现没有肯定性
咱们如今从系统功能出发来分解这些要素:前端
-
用户登陆,用户名/密码就足够了,因此基本用户表就应该只有用户名/密码
-
用户资料维护,只须要用户资料,与用户名关联。用户资料的修改之前也会用表来完成,实际上,你只须要一个文件或一个字段来存储用户全部的资料,由于全部修改每次彻底提交全部资料字段都不为过。很容易理解,你绝对不会将员工word格式的简历存储在数据库中,那么又何须把他的电话号码家庭住址也存储起来?
-
组织结构调整。实际上只是上下级关系的调整,只须要记录每一个组织的上级部门的名字便可,固然专门弄一个关系表也ok。
-
权限列表和权限组维护。权限组单独一张表记录包含的权限名,权限自身是名字的平面表,之间都没有任何关系。具体的缘由本身想去。
-
用户和组织关系维护。创建一张关系表,慢慢维护去吧。通常来讲,从组织来维护用户比较合理,由于人事变动是组织自身的周期性行为,而不是我的的突发性行为。
-
用户和权限关系维护。维护一张关系表,事实上,这张表就足以应付全部的权限校验,所以从优化角度来讲,将权限的命名变得有意义至关重要:根据当前或选定用户,获取他全部的权限,而且经过权限的名字就可以了解具体的权限定义作出判断。
-
组织和权限关系维护。请不要实现为关系表,宁肯将此实现为组织-用户和用户-权限的两次查询在前端作组合。例如某个需求是,A部门下全部员工都可以得到访问a1系统的首页权限,彻底能够实现为:管理员查询A部门下全部员工,选中他们,查找全部权限中是否有“访问a1系统的首页权限”,有的话,赋予当前选择的用户,没有的话新建这么一个名字的权限并赋予当前选择的用户,并在完成后通知a1系统的开发人员,将这个名字加入到校验逻辑中去。
这样一来,咱们有了:数据库
-
用户密码表,用户名/密码2个字段
-
用户资料文件夹,文件按用户名取名。
-
组织结构表,只存名字和上级组织名字,2个字段
-
权限表,权限的名字1个字段
-
权限组表,权限组的名字和所含权限以分隔符分割的联合,2个字段
-
用户和组织关系,用户名和组织名2个字段
-
用户和权限关系,用户名和权限名2个字段
进一步的优化是:json
-
组织以域名写法来规范,例如XX公司XX部XX2科,那就是XX2科.XX部.XX公司,这是ldap/x.500的标准写法(我更倾向于从大到小的中国式写法,这样经过天然排序就可以得到树状结构)。如此命名,连上级组织字段都不用写了。若是用户只有一个组织,那么用户和组织关系表也不用写了。
-
用户的全部权限存为一个字段,以分隔符分割(可选的)。通常来讲,用户权限也就几十个,所有取出没有任何问题,校验方能够很方便的作判断。一个作法是,用户A有权限a1,a2,a3,那么权限字段就是|a1|a2|a3|,a3校验时,只须要作indexOf('|a3|')便可。另外一个优化方案是保证权限名天然有序,这样校验时就能够用2分法加速。
优化结果是:浏览器
-
用户密码表,2字段
-
用户资料文件夹
-
组织结构表,1字段
-
权限表,1字段
-
权限组表,2字段
-
用户和组织关系,2字段,1对1(或1对多,1用户多组织时)
-
用户和权限关系,2字段,1对1(或1对多,方案2)
咱们看一下优化后的好处:缓存
-
用户密码表很重要,能够单独用加密性强的库或者表存它
-
用户资料文件夹能够很方便的作备份,离职员工也可以作资料存档。若是使用json或者xml格式存储的话,浏览器直接解析,对于接口调用来讲太方便了。而且,文件系统能够利用操做系统级别的ACL来管理,安全性细度更高
-
与当前用户相关的东西,除用户资料外,在用户登陆后均可以一次取出,而后塞到session中去。例如他的组织,他的权限列表。因为这些信息很是细碎,并且只在登陆后作一次,不必经过文件缓存。
-
权限、组织结构,均可以一次取出并用json文件缓存供浏览器使用,用户与组织关系可按组织分文件缓存。因为每一个表字段少或者关系清楚,用文件缓存就很容易肯定缓存刷新的时机。