数据类型uuid
是非常适合的任务。varchar
或text
表示,它仅占用16个字节,而RAM中仅占用37个字节。(或者磁盘上有33个字节,但是在许多情况下,奇数需要填充以有效地使其变为40个字节。)这种uuid
类型还有更多优势。
例:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
详细信息和更多说明:
如果不需要md5的加密组件,则可以考虑使用其他(更便宜的)哈希函数,但是对于您的用例,我将使用md5(大多数情况下是只读的)。
一句警告:对于你的情况(immutable once written
)一个函数依赖(伪自然)PK是好的。但是如果有可能进行更新,同样会很痛苦text
。考虑纠正一个错字:PK和所有相关索引,FK列dozens of other tables
以及其他引用也必须更改。表和索引膨胀,锁定问题,更新缓慢,引用丢失,...
如果text
可以在正常操作中进行更改,则替代PK将是更好的选择。我建议使用一bigserial
列(范围为-9223372036854775808 to +9223372036854775807
- 九十二点三十二分之三千万分之三百七十二亿兆三十六亿分之三十亿左右的东西)作为的不同值billions of rows
。在任何情况下都可能是一个好主意:数十个FK列和索引使用8 个字节而不是16个字节!)。或随机UUID的多更大的基数或分布式系统。您总是可以另外存储md5(as uuid
),以便快速从原始文本中查找主表中的行。有关:
至于您的查询:
解决@Daniel的评论:如果您希望不使用连字符的表示形式,请删除要显示的连字符:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
但我不会打扰。默认表示就可以了。问题实际上不是这里的代表。
如果其他各方应该采用不同的方法,并在字符串中添加不带连字符的字符串,那么这也不是问题。Postgres接受几种合理的文本表示形式作为的输入uuid
。文档:
PostgreSQL还接受以下替代形式输入:使用大写数字,用大括号括起来的标准格式,省略一些或所有连字符,在任何四位数组之后添加连字符。例如:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
更重要的是,该md5()
函数返回text
,你会用decode()
转换为bytea
和的默认表示这是:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
您将不得不encode()
再次获得原始文本表示形式:
SELECT encode(my_md5_as_bytea, 'hex');
最重要的是,由于内部开销,存储为的值bytea
将在RAM中占据20个字节(在磁盘上占17个字节,带有padding占24个字节),这特别不利于简单索引的大小和性能。varlena
一切都有利于uuid
这里。