我知道这是超基本的,但这是我一直持有的假设,并且想验证它是否属实(通常,具体针对各种实现的细节)
假设我有一个包含文本列“Fruit”的表。在该专栏中,只出现了四个值中的一个:梨,苹果,香蕉和草莓。我有一百万行。
如果我将其提取到另一个具有Fruit列且只有那四行的表中,然后将原始列作为外键,而不是重复(平均)每个25万次数据,那么它是否会保存空间?
我假设四个水果名称只存储一次,而且百万行现在有指针或索引或某种引用到第二个表中。
如果我的行值比短水果名称长,我认为节省/优化甚至更大。
答案 0 :(得分:6)
外键关系两侧字段的数据类型必须相同。
如果父表的键字段是(例如)varchar(20)
,则从属表中的外键字段也必须是varchar(20)
。这意味着,是的,你必须在每张桌子上重复X万行'Apple'和'Pear'和'Banana',其外键指向水果桌。
通常使用数字字段作为键(int,bigint)更有效,因为那些可以用很少的CPU指令进行比较(通常可以直接进行一次cpu指令比较)。另一方面,字符串需要循环和相对昂贵的设置。所以,是的,最好将水果名称存储在某个表格中,并使用相关的数字ID字段作为外键。
当然,您应该对这两种设置进行基准测试。这些只是一般的拇指规则,您的特定要求/设置实际上可以更快地使用字符串作为键版本。
答案 1 :(得分:5)
这是正确的。
你应该
table fruits
id name
1 Pear
2 Apple
3 Banana
4 Strawberry
ID是主键。
在第二个表中,您将只使用此表的id。这将节省您的物理空间,并使您的选择语句更快地运行。
此外,这种结构可以让您轻松添加新水果。
答案 2 :(得分:2)
而不是重复数据(平均)25万次 每一个,如果我将它提取到另一个具有Fruit列的表中 只是这四行,然后使原始列成为外键, 它节省空间吗?
如果“Fruit”是“查找”表的PRIMARY KEY,则为“否”,因此它也必须是“大”表中的FOREIGN KEY。
但是,如果您在“查找”表中创建一个小的代理PRIMARY KEY(例如整数“id”),而不是在“大”表中使用它作为FOREIGN KEY,那么您将节省空间。
答案 3 :(得分:2)
首先是的,它会节省空间,因为int - 4个字节,TINYINT - 1个字节。其次,使用TYPE INT搜索此字段将比VARCHAR更快。除此之外,如果您的数据将来没有变化,您可以使用ENUM。使用枚举,您将获得与辅助表相同的更快结果,您将避免额外的连接。
答案 4 :(得分:2)
规范化不仅仅是关于空间,它通常是冗余和建模数据行为,也是关于仅更新一行以进行更改 - 并通过仅更新最少量的数据来减少锁的范围。
答案 5 :(得分:1)
可悲的是,你假设错了:为每个引用表重复地物理存储这些值。有些SQL产品确实只存储了一次这个值,但大部分都没有,特别是那些基于磁盘上连续存储的更受欢迎的产品。
这就是最终用户认为需要以伪装使用整数'代理键'来实现自己的点的原因。系统替代品将是优选的,例如对于用户来说是不可见的,就像系统维护索引的“值”并且不能由用户直接操作一样。滚动自己的问题是它们成为逻辑模型的一部分。
答案 6 :(得分:0)
我知道你确实想要使用外键。 Aaah,Marc B刚刚公布了对FKs的影响。 但是使用第二个表作为外部“名称提供者”肯定会节省空间。你需要一个关于fruit.fruit_id的额外索引。这个将是相当小,它将是NUMERIC。比char或varchar上的索引更快。