【发布时间】:2014-02-18 22:04:45
【问题描述】:
我是 SQL 新手,以关系而不是分层来考虑我的数据集对我来说是一个很大的转变。我希望能够深入了解使用数字行 ID 作为主键而不是更有意义的字符串值的性能(在存储空间和处理速度方面)与设计复杂性。
具体来说,这是我的情况。我有一个包含几百行的表(“父”),其中一列是字符串标识符(10-20 个字符),这似乎是表主键的自然选择。我有第二个表(“子表”),其中包含数十万(或可能数百万或更多)行,其中每一行都引用父表中的一行(因此我可以在子表上创建外键约束)。 (实际上,我有几个这两种类型的表,其中包含一组复杂的引用,但我认为这说明了重点。)
所以我需要子表中的一列为父表中的行提供标识符。天真地,似乎将列创建为 VARCHAR(20) 之类的东西来引用第一个表中的“自然”标识符会在存储空间和查询时间方面导致巨大的性能损失,因此我应该包括父表中的数字(可能是 auto_increment)id 列,并将其用作子表中的引用。但是,由于我加载到 MySQL 的数据还没有这样的数字 id,这意味着增加了我的代码的复杂性和更多的错误机会。更糟糕的是,由于我正在进行探索性数据分析,我可能想在不对子表做任何事情的情况下处理父表中的值,所以我必须小心不要意外破坏关系删除行并丢失我的数字 id(我可能会通过将 id 存储在第三个表中或类似的东西中来解决这个问题。)
所以我的问题是,是否存在我可能不知道的优化,这意味着具有数十万或数百万行且一遍又一遍地重复仅几百个字符串值的列比最初出现的浪费更少?我不介意为了简单而牺牲效率,因为这是用于数据分析而不是生产,但我担心我会将自己编码到一个角落,我想做的所有事情都需要大量时间运行。
提前致谢。
【问题讨论】:
-
使用正确的索引,“性能”在很大程度上是“无关紧要的”——开销是恒定的。因此,请从非性能角度考虑问题。
-
1) 您的外键不需要在主键列上。 2) 如果你有一个一对多的关系(一个父母有很多孩子),你孩子的外键列肯定不应该是自动递增的。 3)外键约束可以有类似 RESTRICT 或 CASCADE 以避免意外错误,具体取决于您将要做什么。
-
@Mitch,你是对的,这似乎是重复的!我的搜索失败了。感谢您为我指明正确的方向。看到这是更有经验的数据库人员之间的公开辩论,这也有点令人欣慰。
-
@biogeo,这当然是一场辩论……这是 Windows VS Mac 的 DBA 版本,或者 emacs VS VI。
标签: mysql sql performance