主/外键与没有主键的单个表的性能

时间:2016-04-05 05:10:40

标签: sql sql-server database

如果我有一个可以与多个密钥相关联的用户,则正确的表设置为:

  1. 一个包含两列的表,例如:

    UserName | Key
    

    其中没有主键,用户可以有多行,或者:

  2. 两个具有匹配标识符的表

     Table 1     UserName | UserId
    
     Table 2     Key | UserId
    

    其中UserId是table1的主键和表2的外键。

  3. 如果我想查找与用户关联的所有密钥,哪种方式更受欢迎?

4 个答案:

答案 0 :(得分:2)

如果您想查找与给定用户关联的所有密钥,可以使用以下JOIN查询:

SELECT Key
FROM keys k INNER JOIN users u
    ON k.UserId = u.UserId
WHERE u.UserName = 'username'

在这种情况下,从索引中获益最多的地方将是两个表中的UserId列。如果存在此索引,则对于给定用户,在Key表中查找键将需要大致恒定的时间。

没有任何索引,MySQL将不得不为每个用户进行全表扫描,因为它试图找到与该用户相对应的密钥。

答案 1 :(得分:1)

在这种情况下,没有任何常见不常见!这一切都取决于您的业务需求;如果用户可以拥有多个用户名,则需要有一个表格,将每个用户的所有这些用户名链接在一起,由userId标识,此userId应为因此,在整个数据库设计中用户的标识符,在这种情况下,您需要两个表:

UserDetails将包含用户信息,例如姓名年龄...出生日期等,以及UserNames,其中包含每个用户至少一个userName。

否则,您可以使用相同的表UserDetails来存储userName以及其余的用户详细信息

因此,在您的情况下,使用单独的表来存储userNames,为什么在示例中:

假设您的用户有两个userName。

如果您使用一个表来存储userName的用户信息,您将获得如下数据:

Name       BirthDate      OtherDetails   UserName AnotherDetails
user       1/1/1990        blah blah..    user1    blah blah...
user       1/1/1990        blah blah..    user2    blah blah...

如您所见,上表中的数据会重复

但是如果使用两个表,数据大小将会减少

这称为 database normalization

答案 2 :(得分:1)

如果不了解您尝试建模的实体和属性,则无法回答您提出的问题。

实体关系建模

您的数据模型代表什么实体?实体是可以唯一标识的人,地点,事物,概念或事件,对系统很重要,我们可以存储有关的信息。

根据问题中的描述,我们认为"用户"是一个实体。也许"关键"也是一个实体。我们无法从描述中真实地说明这是一个实体,还是一个重复(多值)属性。

唯一标识"用户"?

的内容

我们需要/想要存储哪些关于"用户"?

的属性

第二部分是理解实体之间的关系

为此,我们需要询问并获得一些问题的答案,例如:

有多少"用户"可以与特定的"键"?

相关联

" key"必须与用户相关,或者密钥是否与零用户相关?

可以"键"除用户外,是否唯一标识?

等等。

基于这些答案,我们可以开始整理一个模型,并评估该模型表示问题的程度,以及该模型对我们预期用例的效果如何。

如果" user"和"关键"是实体,实体之间存在多对多关系,其模型看起来与“" key"不是实体,而只是一个多值属性。

如果某个密钥必须属于"一个且只有一个用户,用户可以"持有"零,一个或多个键,可能它是一个多值属性。然后我们需要两个表。一个父母"表"用户"实体和另一个孩子"用于存储重复属性的表。

我们还不知道(还)唯一标识用户的属性集,因此我们将使用通用" userid"来表示该属性。某种未指定数据类型的属性。

user
-----
userid  datatype    NOT NULL PRIMARY KEY
name    varchar(30) NOT NULL

e.g。

userid  name 
------  ------
psimon  paul simon
agarfu  art garfunkel

为了存储多值属性,我们使用实体表的PRIMARY KEY作为我们第二个" child"中的外键。表

user_key
--------
userid   datatype NOT NULL FOREIGN KEY ref user.userid 
key      VARCHAR(30) NOT NULL

e.g。

user_key
userid  key
------- -------
psimon  G major
psimon  A major
psimon  A major
psimon  B minor
agarfu  A major

如果我们决定"用户"将使用不同的列作为主键,然后我们将相同的列用作子表中的外键。

在这个例子中,我们允许"重复" "键"的值对于给定的用户。如果我们只想要"键"的明确值对于用户,我们需要在(userid, key)元组上添加UNIQUE约束。

在我们过于担心性能之前,我们需要关注获得一些可行的数据模型。从那里,我们可以将其转化为一些实现,并评估每个实现的性能特征。

如果实施中的表没有合适的主键,我们可以引入另一列作为代理"主键。

答案 3 :(得分:0)

只要你的桌子有一个独特的PK,你就基本上是正确的,并在某些地方完成了#34;完美的"到"可以做得更好"。

在你的第一个案例中,你仍然是正确的,只是PK是UserName和Key。

第二个更常见,可能更正确,因为迟早你会想要与用户无关,并且在逻辑上适合UserName表的用户。