3

我有一个包含用户设置集的表,它具有以下列:

UserID INT
Set VARCHAR(50)
Key VARCHAR(50)
Value NVARCHAR(MAX)
TimeStamp DATETIME

UserID 与 Set 和 Key 一起是唯一的。因此,特定用户不能在一组特定设置中拥有两个相同的键。设置是按集合检索的,因此如果用户从某个集合中请求某个密钥,则会下载整个集合,这样下次需要同一集合中的密钥时,就不必去数据库了.

我应该在所有三列(userid、set 和 key)上创建一个主键,还是应该创建一个具有主键的额外字段(例如,一个名为 SettingID 的自动增量整数,我猜这是个坏主意),还是不创建一个主键键,只是创建一个唯一的索引?

- - - 更新 - - -

只是为了澄清一下:这是行表的结尾,无论如何它都没有加入。UserID 是用户表的 FK。Set 不是 FK。它几乎是我的 GUI 的辅助表。举个例子:用户第一次访问网站的某些部分时会得到一个帮助气球,如果他们愿意,他们可以关闭它。一旦他们点击它,我将在“GettingStarted”集中添加一些设置,表明他们的 helpballoon X 已被禁用。下次当用户访问同一页面时,该设置将声明不再显示帮助气球 X。

4

8 回答 8

7

拥有复合唯一键通常不是一个好主意。

将任何业务相关数据作为主键也会给您带来麻烦。例如,如果您需要更改值。如果在应用程序中无法更改该值,则可能会在将来发生,或者必须在升级脚本中进行更改。

最好创建一个代理键,一个没有任何商业意义的自动编号。

更新后编辑

在这种情况下,您可以考虑在概念上没有主键,并使这三列成为复合唯一键的主键(使其可更改)。

于 2009-05-06T08:30:03.573 回答
2

我应该在所有三列上创建一个主键吗(userid, set, and key)

做这个。

使用代理主键将导致额外的列不用于其他目的。

与代理主键一起创建UNIQUE INDEX与创建非集群主键相同PRIMARY KEY,并且会导致额外的KEY lookup,这对性能来说更糟。

创建一个UNIQUE INDEX没有 aPRIMARY KEYHEAP-organized表将需要一个额外RID lookup的值来访问值:也不是很好。

于 2009-05-06T08:29:14.993 回答
1

你有多少钥匙和套装?这些需要是 varchar(50) 还是可以指向查找表?如果您可以将此 Set 和 Key 转换为 SetId 和 KeyId ,那么您可以在 3 个整数值上创建主键,这会更快。

于 2009-05-06T08:39:05.110 回答
0

我可能会尝试确保 UserID 是唯一标识符,而不是在整个代码中重复 UserID。复合键在您的代码生命周期的后期往往会变得混乱。

我假设这是某种配置值的查找字段,因此如果是这种情况,您可能会使用复合键。数据已经存在。您可以使用主键来保证它的唯一性。如果您改变主意并稍后决定它不适合您,您可以轻松添加 SettingId 并使原始复合键成为唯一索引。

于 2009-05-06T08:32:37.203 回答
0

创建一个单独的主键。无论业务逻辑将如何变化,都必须将哪些新规则应用于您的 Key VARCHAR(50) 字段 - 拥有一个主键将使您完全独立于业务逻辑。

于 2009-05-06T08:33:05.437 回答
0

以我的经验,这完全取决于有多少表将使用该表作为 FK 信息。您是否希望其他表中的 3 个额外列只是为了结转 FK?

就我个人而言,我会创建另一个 FK 列并在其他三列上放置一个唯一约束。这使得这张表的外键更容易被吞下。

于 2009-05-06T08:33:27.030 回答
0

最好将 UserID 作为 32 位 newid() 或唯一标识符,因为作为 int 的 UserID 为可能的 UserID 的用户提供了提示。这也将解决您的复合键问题。

于 2009-05-06T08:38:04.943 回答
0

我不是复合键的支持者,但在这种情况下,作为行表的结尾,它可能是有道理的。但是,如果您允许在这三个字段中的任何一个字段中使用空值,因为在插入时其中一个或多个值是未知的,则可能会有困难,唯一索引可能会更好。

于 2009-05-06T13:08:21.097 回答