考虑有一堆表链接到“国家”或“货币”表。
为了使数据更易于阅读,我希望将带有国家代码(例如 US、GB、AU)和货币代码(USD、AUD)的 CHAR 字段作为这两个表中的每一个的主键,并且所有其他表都将使用这个 CHAR 作为一个外键。
数据库是带有innodb引擎的mysql。
它会导致性能问题吗?这是我应该避免的吗?
考虑有一堆表链接到“国家”或“货币”表。
为了使数据更易于阅读,我希望将带有国家代码(例如 US、GB、AU)和货币代码(USD、AUD)的 CHAR 字段作为这两个表中的每一个的主键,并且所有其他表都将使用这个 CHAR 作为一个外键。
数据库是带有innodb引擎的mysql。
它会导致性能问题吗?这是我应该避免的吗?
性能并不是真正的主要问题,至少对我来说不是。问题更多关于代理与自然键。
国家代码不是静态的。他们可以而且确实会改变。国家更改名称(例如埃塞俄比亚改为厄立特里亚)。它们产生(例如南斯拉夫或苏联的解体)并且它们不复存在(例如西德和东德)。当这种情况发生时,ISO 标准代码会发生变化。
自 1990 年以来的更多名称变化:国家、城市等
代理键往往更好,因为当这些事件发生时,键不会改变,只有引用表中的列会改变。
出于这个原因,我更倾向于使用 int 主键创建国家和货币表。
话虽如此,varchar 键字段将使用更多空间并具有某些性能劣势,除非您执行大量查询,否则这可能不会成为问题。
为了完整起见,您可能需要参考AppDevelopers 的数据库开发错误。
James Skidmore 的链接很重要。
如果您将自己限制为国家和货币代码(分别为 2 和 3 个字符),您很可能能够避免声明 char(2) 和 char(3) 列。
我想这不会是一个禁忌。如果您使用的是 8 位字符编码,那么您将分别查看大小为 smallint 或 mediumint 的列。
我的回答是没有明确的答案。只需在您的项目中选择一种方法并保持一致。两者都有其优点和缺点。
@cletus 对使用生成的密钥提出了一个很好的观点,但是当您遇到数据相对静态的情况(例如国家/地区代码)时,为它们引入生成的密钥似乎过于复杂。尽管存在现实世界的政治,但对于大多数业务问题而言,国家代码的出现和消失并不是什么大问题(但如果您的数据积极关注所有 190-210 个国家/地区,请遵循该建议)。
普遍使用代理键是一种很好且流行的策略。但请记住,它是对使用自然键对所有内容进行建模的数据库的响应。确认!打开一本 15 年前的数据库书。在任何地方使用自然键肯定会让您陷入困境,因为对问题域的初步理解被证明是错误的。您确实希望在建模实践中保持一致性,但是对于明显不同的情况使用不同的技术是可以的。
我怀疑大多数现代数据库在 var(2) 外键上的性能将与 int 字段相同(或更好)。多年来,数据库一直支持文本外键。
鉴于我们没有关于该项目的其他信息,如果您更喜欢使用国家代码作为外键,并且您可以选择这样做,我会说没关系。处理数据会更容易。这有点违背当前的做法,但是——在这种情况下——它不会让你陷入困境。