存在复合键时,主键中不包含唯一ID字段

时间:2012-03-03 19:37:19

标签: database-design indexing sql-server-2008-r2 primary-key

我正在尝试在SQL Server 2008 R2中构建一个允许用户将自己的子类型放入类别的数据库。我有一个父表,其中包含预设的类别名称(由我定义)。

我面临的问题是处理PRIMARY KEYUNIQUE约束以及外键REFERENCES的最佳方法是什么。索引是这个的中心,因为我预计子表(我们称之为CategoryTypes)会随着时间的推移而变得非常大,并且需要能够有效地允许基于父表的数据读取( Categories)。如果表格的布局如下,我是否需要预测?

我担心的是IDENTITY表中的CategoryTypes列需要保持唯一计数。我包含此字段的原因是在应用程序中的层之间传递数据时允许更简单的引用。通过传递整数与整数/字符串对。这些表中的数据将保留在数据库的每一层,以节省带宽。从数据库的角度来看,下面的布局在部署后是否会带来任何重大挑战?

为了简化,使用复合键存在时主键中未包含的唯一ID字段(IDENTITY)是否存在问题?见下面的表格布局:

父表:

CREATE TABLE schema.Categories
(
  Id TINYINT PRIMARY KEY NOT NULL,
  Name VARCHAR(100) NOT NULL,
)

子表(用户随时间插入的数据):

CREATE TABLE schema.CategoryTypes
(
   Id INT IDENTITY(1,1) NOT NULL,
   CategoryId TINYINT REFERENCES schema.Categories(Id) NOT NULL,
   Name VARCHAR(100) NOT NULL,
   CONSTRAINT PRIMARY KEY CLUSTERED(CategoryId, Name)
   CONSTRAINT UC_CategoryTypesId UNIQUE NONCLUSTERED(Id)
)

1 个答案:

答案 0 :(得分:0)

你所描述的听起来有点像继承结构。据我所知,我已经创建了一个示例数据集。你能证实这是你的意图吗?

如果是,那么这应该可以正常工作,我不明白为什么你没有将CategoryType.Id设置为主键?如果它不是你的PK,也没有在其他地方被引用为FK,那么我没有看到它的重点。我个人认为你没有获得足够的带宽节省,而且应该只是按CategoryId和Name请求数据。实际上,通常没有PK表示继承结构的表示方式(How can you represent inheritance in a database?)。

如果您必须按照设置的方式保留它,我个人建议将Id设置为PK,并在CategoryId / Name上设置唯一约束。

这只是我的两分钱。

Category
----
Id|Name
1 |Food
2 |Drink

CategoryType
----
Id|CategoryId|Name
1 |2         |Water
2 |2         |Orange Juice

更新的答案(直接解决性能问题)

首先,如果不是问题,我建议不要过分担心。这是我们许多人常见的问题,过度复杂的东西不需要它。这属于我书中的KISS principle

但是,如果你试图按照你解释的方式提前解决这个问题,那么这是我的额外想法:

  • 将PK创建为Id,但将其设为NONCLUSTERED
  • 在CategoryId上创建聚簇索引,并考虑在上述非聚簇索引上使用INCLUDE keyword
  • 如果您经常使用CategoryId进行查询,则只执行上述操作,而不是使用CategoryType.Id
  • 创建密钥时的考虑因素(即使是从INCLUDE文章中获取)
Index maintenance may increase the time that it takes to perform modifications
, inserts, updates, or deletes, to the underlying table or indexed view.

最终,我认为你所做的事情会很好,但PK不必聚集,所以我肯定会把PK移到Id字段。如果要在CategoryId或CategoryId / Name上创建集群,或者如果您想按照我的建议尝试使用INCLUDE,则可以选择它。这实际上取决于表的使用方式,因此比较执行计划可能会有所帮助。

希望这有助于:)