使用char作为主键/外键是不是没有?

时间:2009-09-14 00:26:57

标签: sql mysql database-design data-modeling innodb

考虑到有一堆表链接到“国家”或“货币”表。

为了使数据更易于阅读,我想将国家代码(例如US,GB,AU)的CHAR字段和货币代码(USD,AUD)作为这两个表中每个表的主键,所有其他表将使用这个CHAR作为一个外键。

数据库是带有innodb引擎的mysql。

是否会导致性能问题?这是我应该避免的吗?

3 个答案:

答案 0 :(得分:21)

性能不是主要问题,至少不适合我。问题更多的是代理与自然密钥。

国家/地区代码不是静态的。他们可以而且确实会改变。国家改名(例如埃塞俄比亚到厄立特里亚)。它们应运而生(例如南斯拉夫或苏联解体)并且它们不复存在(例如西德和东德)。发生这种情况时,ISO标准代码会更改。

Name Changes Since 1990: Countries, Cities, and More

中的更多内容

代理键往往更好,因为当这些事件发生时,键不会改变,只有参考表中的列可以改变。

出于这个原因,我更倾向于使用int主键创建国家/地区和货币表。

话虽这么说,varchar关键字段将使用更多空间并具有某些性能缺点,除非您执行大量查询,否则可能不会成为问题。

为完整起见,您可能需要参考Database Development Mistakes Made by AppDevelopers

答案 1 :(得分:1)

James Skidmore的链接很重要。

如果您将自己限制在国家/地区和货币代码(分别为2个和3个字符),您很可能会声明列char(2)和char(3)。

我猜这不会是禁忌。如果您使用的是8位字符编码,则会分别查看smallint或mediumint大小的列。

答案 2 :(得分:0)

我的回答是没有明确的答案。只需在项目中选择一种方法并保持一致。两者都有其优点和缺点。

@cletus对使用生成的密钥提出了一个很好的观点,但是当你遇到数据相对静态的情况时,比如国家代码,为它们引入生成的密钥似乎过于复杂。尽管存在真实的世界政治,但是对于大多数商业问题来说,让国家代码出现和消失并不是真正的问题(但如果您的数据主动关注所有190-210个国家,请遵循该建议)。

普遍使用代理键是一种很好的流行策略。但请记住,它是为使用自然键建模数据库而做出的。确认!打开一本15岁的数据库书。在任何地方使用自然键肯定会让你陷入困境,因为对问题域的初步理解证明是错误的。您确实希望在建模实践中保持一致,但是对于明显不同的情况使用不同的技术是可以的。

我怀疑var(2)外键上大多数现代数据库的性能与int字段相同(或更好)。数据库多年来一直支持文本外键。

鉴于我们没有关于该项目的其他信息,如果您希望使用国家/地区代码作为外键,并且您可以选择这样做,我会说没关系。处理数据会更容易。这与当前的做法有点不同,但是 - 在这种情况下 - 它不会让你回到某个角落。