PostgreSQL使用UUID与Text作为主键比较
在处理UUID数字时,将它们存储为数据类型uuid。始终如此。没有任何好理由考虑text作为替代方案。输入和输出默认都是通过文本表示完成的。类型转换非常廉价。
text数据类型在RAM和磁盘上需要更多空间,处理速度较慢,并且更容易出错。提供了大部分原理的答案提供了相关解释(由于你的现有实现,他没有得出相同的结论)。
这些问题以前都已经被问过、回答过并进行过讨论。与此相关的详细解释的dba.SE相关问题有:
- [所有值都是36个字符时,使用char还是varchar进行索引查找是否更快?](https://dba.stackexchange.com/q/89429/3684)
- [MD5字段的最佳数据类型是什么?](https://dba.stackexchange.com/q/115271/3684)
也许你根本不需要UUID(GUID)。可以考虑使用bigint。它只占用8个字节,在各个方面都更快。它的范围经常被低估:
-9223372036854775808到+9223372036854775807
这是92亿亿亿个正数。也就是说,9223万亿亿亿亿亿亿个正数。
如果每秒烧毁100万个ID(这是一个非常高的数字),你可以持续这样做292471年。然后又持续292471年进行负数。 "数千万"还远远不够。
UUID实际上只适用于分布式系统和其他特殊情况。
问题:在使用PostgreSQL时,使用UUID还是Text作为主键的原因以及解决方法是什么?
原因:
1. 使用UUID作为主键会使索引变大,因为UUID的字符串值较大;
2. 在理论上,比较索引时,字符串值的比较会稍慢一些;
3. 对于需要查询大量数据的情况,顺序扫描可能是更好的选择,这可能导致性能问题。
解决方法:
1. 对于需要查询大量数据的情况,可以使用查询结果的分块和UNION
的方法来优化性能;
2. 对于索引的性能问题,GUID类似于md5sums、sha1等,通常在大多数情况下可以很好地进行索引,并且不需要顺序扫描;
3. 对于具有大量行的表格,布尔索引可能不起作用,因为对于索引中的每个值(true、false和NULL),都会有大量的行碰撞。而GUID索引理论上会有大量不重复的值。
关于PostgreSQL是否识别字符串为GUID的问题,PostgreSQL默认不会将字符串识别为GUID,它只认为是唯一的字符串。但对于某些需要特定GUID行为的情况,可以通过将字符串转换为UUID来满足需求。例如,可以使用::uuid
将文本列foo
转换为uuid
类型。
在使用PostgreSQL时,使用UUID还是Text作为主键,对于大多数情况下的性能影响不大。如果遇到性能问题,应该先考虑其他查询优化方法,而不是直接修改主键数据类型。PostgreSQL默认将字符串视为唯一的字符串,但如果需要,可以将字符串转换为UUID进行特定的操作。