Ric*_*ACC 4 sql t-sql database database-design
我的数据库有两个表,一个包含用户列表,另一个包含角色列表.每个用户都属于一个或多个角色,当然每个角色中都有多个用户.
我有两种方法来链接信息.第一种是添加第三个表,其中包含两个表中的ID.然后,简单连接将返回属于角色的所有用户或用户所属的所有角色.但是,随着数据库的增长,这些简单查询返回的数据集将呈指数级增长.
第二种方法是向users表添加一列,其中存储了分隔的角色列表.这将消除对第三个链接表的需要,这可能对数据库增长产生积极影响.缺点是SQL无法使用分隔列表.我发现处理该信息的唯一方法是使用临时表和自定义函数.
正在查看我的执行计划,"表扫描"事件是占用最多资源的事件.从等式中消除一个表会加快速度,这是有道理的.该功能占用的资源不到1%.
这些测试是在少于20条记录的数据库上完成的.随着数据库大小的增长,表扫描将花费更长时间,因此限制它们可能是最佳选择.
如果使用分隔列表是一个很好的方法,为什么没有人这样做?
请告诉我哪个是你喜欢的方法(即使它与我的两个不同)以及为什么.
谢谢.
gre*_*mac 10
如果你有一个分隔列表,找到具有给定角色的用户将变得非常昂贵:实际上,你需要对该表进行全面扫描,并查看每一行中该列的所有值,试图查看是否它包含一个给定的角色.
一个单独的表(规范化,多对多关系)是要走的路,通过适当的索引,您将无法进行全面扫描.
例如:
User: UserId, Name, ....
Role: RoleId, Name, ....
UserRole: UserRoleId, UserId, RoleId
Run Code Online (Sandbox Code Playgroud)
(UserRoleId是可选的,你也可以让PK为UserId + RoleId,我不会在这里讨论代理与复合键的讨论)
您需要一个UNIQUE上的(UserId,RoleId)索引来强制执行重复操作.这也有助于您尝试查看特定用户是否具有特定角色的任何查询(WHERE userId = x AND roleId = y)
如果您正在查找用户拥有的所有角色,那么您只需要UserId上的索引.
相反,如果您正在查找给定角色的所有用户,则只有roleId的索引会加快速度.如果你不进行这个查询,或者很少这样做,那么没有这个索引会为插入/更新稍微加快性能,因为它少做一件事.这是数据库调优的谨慎平衡行为.
表扫描意味着您没有任何索引,或者您的查询不允许使用它们.在安全数据库中,除非是管理员应用程序,否则您很少需要下载整个用户/角色列表.您需要在设计中解决这个问题.
定界列表违反了第一范式(1NF),并且几乎总是会导致长期问题.如果要检索特定角色中的所有用户,会发生什么?你怎么写那个查询?不要走这条路.将其标准化.
如果您使用的是正确的列类型(即不是一个varchar(4000)或varchar(max)任何地方),那么磁盘空间确实不应成为问题.是的,它会"成倍地"增长 - 那又怎样?数据库擅长这种扩展.除非您尝试在10 gig硬盘上运行此功能,否则不必担心.如果你正在尝试将10演出的硬盘驱动器上运行它,你可能有更大的问题担心.
简短回答:不要使用分隔列表.规范化.