SQL表链接...是否更好地拥有链接表或分隔列?

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的索引会加快速度.如果你不进行这个查询,或者很少这样做,那么没有这个索引会为插入/更新稍微加快性能,因为它少做一件事.这是数据库调优的谨慎平衡行为.


Aar*_*ght 8

  1. 表扫描意味着您没有任何索引,或者您的查询不允许使用它们.在安全数据库中,除非是管理员应用程序,否则您很少需要下载整个用户/角色列表.您需要在设计中解决这个问题.

  2. 定界列表违反了第一范式(1NF),并且几乎总是会导致长期问题.如果要检索特定角色中的所有用户,会发生什么?你怎么写那个查询?不要走这条路.将其标准化.

  3. 如果您使用的是正确的列类型(即不是一个varchar(4000)varchar(max)任何地方),那么磁盘空间确实不应成为问题.是的,它会"成倍地"增长 - 那又怎样?数据库擅长这种扩展.除非您尝试在10 gig硬盘上运行此功能,否则不必担心.如果你正在尝试将10演出的硬盘驱动器上运行它,你可能有更大的问题担心.

简短回答:不要使用分隔列表.规范化.


Mit*_*eat 6

第一个选择.它被称为多对多连接表.如果您创建适当的索引,这将执行正常.

不要选择第二个"非规范化"选项.


Hog*_*gan 5

你可以使用单独的桌子,或者你可以用凿子回到穴居人那里。这个选择由你。