我做过很多网络应用程序,你做的第一件事就是创建一个包含用户名、密码、姓名、电子邮件和所有其他常见问题的用户表。我目前的项目提出了一种情况,即非用户记录需要与用户类似的功能,但不需要成为一阶用户的能力。
创建第二个表是否合理people_tb
,即主关系表和数据存储,并且仅使用users_tb
用于身份验证?分离是否user_tb
存在people_tb
任何问题?如果通常这样做,有哪些策略和解决方案以及缺点?
我做过很多网络应用程序,你做的第一件事就是创建一个包含用户名、密码、姓名、电子邮件和所有其他常见问题的用户表。我目前的项目提出了一种情况,即非用户记录需要与用户类似的功能,但不需要成为一阶用户的能力。
创建第二个表是否合理people_tb
,即主关系表和数据存储,并且仅使用users_tb
用于身份验证?分离是否user_tb
存在people_tb
任何问题?如果通常这样做,有哪些策略和解决方案以及缺点?
这当然是一个好主意,因为您正在规范化数据库。我在正在编写的应用程序中做了类似的设计,其中有一个员工表和一个用户表。用户可能来自外部公司或员工,所以我有单独的表,因为员工始终是用户,但用户可能不是员工。
您将遇到的问题是,无论何时使用 user 表,您几乎总是希望 person 表获取您想要显示的名称或其他常见属性。
从编码的角度来看,如果您使用的是直接 SQL,那么在精神上解析 select 语句将需要更多的努力。如果您使用的是 ORM 库,可能会稍微复杂一些。我对这些没有足够的经验。
在我的应用程序中,我用 Ruby on Rails 编写它,所以我经常做一些事情,比如employee.user.name,如果我把它们放在一起,它就只是employee.name 或user.name。
从性能的角度来看,您正在访问两个表而不是一个,但是如果有适当的索引,它应该可以忽略不计。如果你有一个包含主键和人名的索引,例如,数据库会命中用户表,然后是人表的索引(几乎直接命中),所以性能几乎与有一张桌子。
您还可以在数据库中创建一个视图以保持两个表连接在一起,从而为您提供额外的性能增强。我知道在更高版本的 Oracle 中,如果需要提高性能,您甚至可以在视图上放置索引。
我经常这样做,因为对我来说,“用户”(用户名、密码、创建日期、上次登录日期)的概念与“人”(姓名、地址、电话、电子邮件)不同。您可能会发现的缺点之一是您的查询通常需要更多的连接才能获得您正在寻找的信息。例如,如果您只有一个登录名,则需要加入“人员”表以获取名字和姓氏。如果您基于用户 id 主键的所有内容,这会有所缓解,但仍会弹出。
如果 user_tb 有 auth 信息,我非常愿意将其与 people_tb 分开。但是,我会保持两者之间的关系,并且大多数用户的信息将存储在 people_tb 中,除了身份验证所需的所有信息(我想不会用于其他用途)它是设计和效率之间的一个很好的权衡我思考。
这绝对是我们所做的,因为我们拥有数百万人的记录并且只有数千名用户。我们还将地址、电话和电子邮件分开到关系表中,因为许多人拥有不止一个这些东西。关键是不要依赖名称作为标识符,因为名称不是唯一的。确保通过某种类型的代理键(最好是整数或 GUID)而不是名称来连接表。
我总是尽量避免数据重复。如果不是所有的人都需要登录,您可以有一个通用people
表,其中包含适用于人和用户的信息(例如,名字、姓氏等)。
然后对于登录的人,您可以拥有一个users
与 1~1 关系的表people
。该表可以存储用户名和密码。
我会说去规范化设计(两个表),并且只去规范化(去一个用户/人员表),如果它真的会让你的生活更轻松的话。但是,如果实际上所有人都是用户,那么预先进行非规范化可能会更简单。由你决定; 我已经使用了标准化的方法,没有问题。
很合理。
例如,请查看此处的 aspnet_* 服务表。
他们的内置模式有一个aspnet_Users
和aspnet_Membership
后面的表,其中包含有关给定用户的更多扩展信息(散列密码等),但aspnet_User.UserID
用于参考完整性等模式的其他部分。
最重要的是,如果属性是不同的实体,则将属性放在单独的表中是非常常见且良好的设计,就像您的情况一样。