我的数据库中已经有几百万行了。当我设计我的架构时,我不知道 PostgreSQL UUID 数据类型。
其中一张表有 1600 万行(每个分片大约 350 万到 400 万条记录),每天增长大约 50 万条记录。如果需要,我仍然可以将生产系统关闭几个小时。我不会在一两个星期内享受这种奢侈。
我的问题是,这样做值得吗?我想知道 JOIN 性能、磁盘空间使用(完整的 gzip 转储为 1.25 GiB),以及这种性质的事情。
表架构是:
# \d twitter_interactions
Table "public.twitter_interactions"
Column | Type | Modifiers
-------------------------+-----------------------------+-----------
interaction_id | character(36) | not null
status_text | character varying(1024) | not null
screen_name | character varying(40) | not null
twitter_user_id | bigint |
replying_to_screen_name | character varying(40) |
source | character varying(240) | not null
tweet_id | bigint | not null
created_at | timestamp without time zone | not null
Indexes:
"twitter_interactions_pkey" PRIMARY KEY, btree (interaction_id)
"twitter_interactions_tweet_id_key" UNIQUE, btree (tweet_id)
"index_twitter_interactions_on_created_at" btree (created_at)
"index_twitter_interactions_on_screen_name" btree (screen_name)
Triggers:
insert_twitter_interactions_trigger BEFORE INSERT ON twitter_interactions FOR EACH ROW EXECUTE PROCEDURE twitter_interactions_insert_trigger()
Number of child tables: 9 (Use \d+ to list them.)
我会考虑更改为 UUID 类型。
char(36)
占用 40 个字节,uuid
占用 16 个字节,因此每行将节省 24 个字节,这相当于每天 12 MB,一年后节省 4 GB。加索引。根据您拥有的硬件,这并不多,但它可能是。如果你有更多这样的改进机会,它就会增加。此外,我在您的架构中没有看到任何约束,以确保它
interaction_id
实际上是正确的格式。使用正确的类型也会给你。但是,如果您喜欢这样,那么使用
bigint
将节省更多并具有更好的性能。您的应用程序不太可能太大以至于bigint
ID 列不起作用。无论如何,我都不是 postgres 人,但根据我从 SQL Server 了解到的情况,您可以放入数据页的行越多,您将获得的性能越好(从磁盘读取数据通常是最昂贵的操作)。因此,从 36 个1字节宽的字段变为 16 字节GUID似乎可以直接节省成本。您可以进行的读取越少,返回结果的速度就越快。当然,所有这些都假设 GUID/UUID 满足表的业务需求。如果 UUID 满足它,那么bigint会满足吗?这将进一步减少每行 8 个字节的存储成本。
编辑1
对于Postgres 中的字符数据,它们需要额外的存储成本。127 个字节以下的短字符串有 1 个字节的开销,而任何更长的字符串有 4 个字节,这就是第二个响应者如何为 36 个字节的字段提出 40 个字节的成本。但是还有一个字符串压缩选项,所以也许它不会花费全部 40。我不知道最终成本是多少,但基本原理仍然存在:超过 16 字节的任何内容都会增加存储成本,读取时间更长并消耗更多内存。
除了空间问题,请记住,您需要更改每个表以使用正确的数据类型,否则您的连接性能将严重下降。
除了节省数据和索引的大小(正如其他人所说),这确实转化为 I/O 节省,您需要考虑的是您将如何生成新值
interaction_id
以及对索引和查询条件(连接)。对于索引 - 它会更小,但是如果您的很多查询使用索引扫描切换到 UUID 可能会导致索引扫描不可能(取决于您将如何生成 UUID)并且
bigint
可能是更好的选择。最后,由于实际的性能影响还取决于您的使用模式和数据分布,您应该运行测试并拥有一个可以测试您的更改的开发和测试环境。
这将为您提供关于对性能的影响的更准确的答案。