假设我有一张非常大的桌子,车主是这样的:
OWNERSHIP
owner | car
---------------
steven | audi
bernahrd | vw
dieter | vw
eike | vw
robert | audi
... one hundred million rows ...
如果我重构它:
OWNERSHIP
owner | car <-foreign key TYPE.car_type
---------------
steven | audi
bernahrd | vw
dieter | vw
eike | vw
robert | audi
...
TYPE
car_type |
---------------
audi
vw
我是否以空格或速度获胜,或者我是否需要在car_type上创建一个INTEGER代理键?
答案 0 :(得分:3)
整数将占用4个字节,即one more byte than "vw" will。碰巧,PostgreSQL enums take up 4 bytes too,所以你不会通过切换到这种表示来获得任何存储方式(除了它改变枚举本身所带来的困难)。无论如何,查询都会同样快,因为无论如何,只要有一个大小的表,你就会查询索引。数据库性能,尤其是表变大时,基本上是I / O而不是CPU性能。我不相信整数索引会比短字符串上的索引更小或更快,特别是当你有大量的行引用一小组可能的值时。它肯定不会成为您应用程序的瓶颈。
即使我们假设您能够使用人工密钥恢复4个字节,您还要节省多少存储空间?理想情况下,4个字节乘以1亿行约400 MB。您是否因此需要在您的honkin'数据库服务器上搜索少量存储空间?这假设您将其重构为自己的表并使用正确的外键。
当然,回答这个问题的正确方法不是从第一原则来论证。拿你的1亿行表并以两种方式工作。然后自己检查尺寸,如下:
SELECT pg_size_pretty(pg_total_relation_size('ownership')));
SELECT pg_size_pretty(pg_total_relation_size('ownership2')));
使用EXPLAIN ANALYZE进行测试查询,如下所示:
EXPLAIN ANALYZE SELECT * FROM ownership WHERE car = 'audi';
EXPLAIN ANALYZE SELECT * FROM ownership2 WHERE car_id = 1;
比实际花费更多关注实际花费的时间,但要考虑成本。如果可能,在与生产相同的数据库服务器上执行此操作;如果没有,具有相同PostgreSQL配置的类似机器。然后你会有很难的数字来告诉你你付出了什么以及你得到了什么。我怀疑你会发现使用人工密钥并且性能相当时,空间使用情况会稍差一些。
如果这就是您所发现的,请执行关系并使用自然键,并且不要过于担心优化物理存储。空间是您拥有的最便宜的商品。
答案 1 :(得分:1)
使用两个表和字符串外键当然会比使用一个表使用更多的空间。还要多少取决于您拥有多少种类型的汽车。
您应该使用整数car_id
:
如果重复使用相当比例的汽车名称,使用整数键可以节省空间。
如果您需要索引car
列,那么更多,因为整数索引远小于字符串索引。
同样比较整数比比较字符串要快,所以开车搜索也应该更快。
较小的表意味着较大的部分,如果它适合缓存,所以访问它也应该更快。