【问题标题】:MySQL Performance: NOT NULL UNIQUE constraint on natural keys vs separate natural key => surrogate key mappings (tables)MySQL 性能:自然键与单独自然键的 NOT NULL UNIQUE 约束 => 代理键映射(表)
【发布时间】:2011-10-22 12:25:57
【问题描述】:

这是一个小设计,在自然键上具有常见的 NOT NULL UNIQUE 约束:

CREATE TABLE 'users' {
    id int(10) NOT NULL AUTO_INCREMENT,
    name NOT NULL UNIQUE,
    email NOT NULL UNIQUE,
    pass NOT NULL,
    PRIMARY KEY ('id')
}

NOT NULL UNIQUE 约束对我来说似乎是 hackish。拥有不相交的候选键对我来说似乎是非规范化的,并且 UNIQUE 约束似乎是一个臃肿的 O(N) 检查功能,所以我倾向于使用与每个自然键都有关系的设计,将自然键映射到代理键在主要关系中。

CREATE TABLE users {
    id int(10) NOT NULL AUTO_INCREMENT,
    pass NOT NULL,
    PRIMARY KEY ('id')
}
CREATE TABLE user_names {
    name NOT NULL,
    user_id NOT NULL,
    PRIMARY KEY ('name')
}
CREATE TABLE user_emails {
    email NOT NULL,
    user_id NOT NULL,
    PRIMARY KEY ('email')
}

这样,我隐含地对用户的电子邮件和用户名强制执行唯一约束,同时提供能够在 O(ln N + ln M) 时间内使用用户的电子邮件或姓名搜索用户信息的奢侈(我非常喜欢欲望)。

我能看到第一个更常见的设计与第二个设计的性能相匹配的唯一方法是,如果 UNIQUE 约束隐式索引表,以便选择自然键并因此检查其唯一性,则可以完成在 O(ln N) 时间内。

我想我的问题是,关于使用自然键的性能插入和选择,处理具有 3 个或更多由代理键索引的自然键的表的最佳方法是什么?

【问题讨论】:

  • 在您的第二个模式中,一个用户 (users.id) 可以有多个姓名和电子邮件。在第一个中,只有一个。正如@dportas 所提到的,在第一个模式名称和电子邮件中强制执行 NOT NULL,在第二个中可以为 NULL - 好吧,缺失。不确定比较这两种模式的性能是否有意义。
  • “有不相交的候选键对我来说似乎是非规范化的” 与许多设计元素不同,规范化是基于形式逻辑的,所以这是事实问题,而不是意见问题。在达到 6NF 之前,拥有多个候选键不会违反规范化规则。 (根据我的经验,这是一种罕见的状态。)我建议您研究规范化,直到拥有多个候选键似乎更正常为止。 (咳嗽)

标签: mysql database-design


【解决方案1】:

看来你描述的是6th Normal Form。假设您的原始表在 5NF 中,那么由 3 个表组成的新模式在 6NF 中。拥有三个候选键不会违反 5NF,但会违反 6NF。

从数据完整性的角度来看,但是 6NF 有很大的缺点。通常情况下会丢失一些依赖项。例如,您的原始表强制每个用户都有一个名称和密码的约束。您的 6NF 版本无法做到这一点——如果您想允许插入所有表,至少在 SQL 中不会。 6NF 对于某些特定情况(时间数据)很有用,但一般而言,从数据完整性的角度来看,5NF 更有用且更可取。

这并不能回答您的性能问题,但我认为值得指出。

【讨论】:

  • 我同意,但我会补充一点,性能会受到影响,因为进行连接确实有成本,我认为如果您认为现在您必须根据 Mitchell 描述的内容进行 3 次插入而不是 1 次插入,那么我认为这是相当明显的.
  • 感谢您的意见。 @Icarus:但某些搜索速度更快
  • @Mitchell,由于这两种模式在逻辑上非常不同,我不确定仅在性能上比较它们是否明智。它们不会对同一组需求进行建模,因此您不会进行同类比较。
  • @dportas:是的,感谢您的回答,我现在意识到这一点。我显然关心优化第一个方案的性能。将表中的自然键与主键索引一起索引是否明智,本质上是创建多个主键?
  • @Mitchell。是的。如果多个键能准确地为业务领域建模,那么它们是非常有意义的,并且通常索引一个键是有意义的。大多数 SQL DBMS 都需要索引来执行密钥。
【解决方案2】:

在我看来,你规范化太多了。您不仅会损害插入/更新的性能,还会损害选择的性能,因为您现在要连接 3 个表,而不是在一个表中直接插入/选择/更新/删除。

我不同意 NOT NULL UNIQUE 是骇人听闻的,但我确实觉得奇怪的是 name 列上有这样的约束。

【讨论】:

  • 哦,对了,我没有考虑根据 id 来查找姓名/电子邮件。此外,名称/密码是登录凭据。
  • @Mitchel 在这种情况下,请考虑在您首先描述的用户表中将名称列重命名为“用户名”,因为看到具有唯一约束的名称列会让人感到困惑。
  • @Icarus,这是规范化的示例,而不是de规范化。
  • @dportas 对不起,你是对的。标准化,我的意思是。谢谢,我会更正我的说法。
猜你喜欢
  • 2013-12-01
  • 2011-12-19
  • 2012-09-26
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多