1

假设我有一张非常大的桌子,里面有这样的车主:

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 代理键?

4

2 回答 2

4

整数将占用 4 个字节,比 "vw" 多一个字节。碰巧的是,PostgreSQL 枚举也占用了 4 个字节,因此通过切换到这种表示,您不会获得任何存储方面的东西(除了它对更改枚举本身带来的困难)。无论哪种方式,查询都一样快,因为对于这样大小的表,无论如何您都将查询索引。数据库性能,尤其是当表变大时,本质上是 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 配置的类似机器。然后你就会有硬性的数字来告诉你你付出了什么,你得到了什么。我的怀疑是,您会发现使用人工密钥的空间使用情况会稍差一些,并且性能相当。

如果这是您发现的,请做相关的事情并使用自然键,而不必担心优化物理存储。空间是你拥有的最便宜的商品。

于 2013-02-13T21:33:08.090 回答
1

使用两个表和字符串外键当然会比使用一个使用更多的空间。多少取决于您拥有多少种汽车。

你应该使用整数car_id

  • 如果大量汽车名称重复,使用整数键将节省空间。

  • 如果您需要索引car列,则更是如此,因为整数索引比字符串索引小得多。

  • 比较整数也比比较字符串要快,所以汽车搜索也应该更快。

  • 较小的表意味着如果它适合缓存则较大的部分,因此访问它也应该更快。

于 2013-02-13T20:58:18.633 回答