结合使用postgresql唯一索引和函数索引

结合使用postgresql唯一索引和函数索引,postgresql,Postgresql,我有一个如下的postgresql表 CREATE TABLE "user" ( "id" integer NOT NULL, "hash" char(40) NOT NULL, "username" char(255) NOT NULL, PRIMARY KEY ("id"), UNIQUE ("hash")); 然而,由于散列是40个字母,我想做一个如下的函数索引来减少内存需求 CREATE INDEX CONCURRENTLY on user (substr(hash, 0, 20))

我有一个如下的postgresql表

CREATE TABLE "user" (
"id" integer NOT NULL,
"hash" char(40) NOT NULL,
"username" char(255) NOT NULL,
PRIMARY KEY ("id"),
UNIQUE ("hash"));
然而,由于散列是40个字母,我想做一个如下的函数索引来减少内存需求

CREATE INDEX CONCURRENTLY on user (substr(hash, 0, 20))
这样做可以吗,还是只会生成另一个无用的索引?如何确保唯一索引只索引哈希中的前20个字符


谢谢。

如果您需要哈希值是唯一的,那么您必须对整个内容有一个唯一的索引。否则,对于仅在最后20个字符中不同的哈希,您将得到唯一的冲突

您可以在左侧20个字符上创建一个非唯一索引,如图所示:

CREATE INDEX on user (left(hash, 20))
但它可能没有什么用处。当您将整个40字符哈希声明为
unique
约束时,PostgreSQL将自动为其创建唯一索引。如果不删除约束,则无法删除此索引。因此,如果要强制哈希的唯一性,就必须使用全尺寸索引。考虑到这一点,功能性指数不太可能有多大好处。即使在以下查询中:

SELECT ...
FROM "user"
WHERE left(hash, 20) = left($1, 20) AND hash = $1 
如果您认为使用较小的索引首先进行快速检查是在节省时间,那么实际上,PostgreSQL很可能会忽略函数索引而选择完整索引,因为它更具选择性

我不完全清楚您想要实现什么,但是如果它使用部分索引或函数索引来实现唯一约束,您就不能这样做


另外,将
hash
存储为
bytea
,并使用索引表达式
left(hash,20)
。或者可能是10,如果您当前以每字节2个字符的十六进制表示形式存储。

如果您需要散列是唯一的,则必须对整个内容具有唯一的索引。否则,对于仅在最后20个字符中不同的哈希,您将得到唯一的冲突

您可以在左侧20个字符上创建一个非唯一索引,如图所示:

CREATE INDEX on user (left(hash, 20))
但它可能没有什么用处。当您将整个40字符哈希声明为
unique
约束时,PostgreSQL将自动为其创建唯一索引。如果不删除约束,则无法删除此索引。因此,如果要强制哈希的唯一性,就必须使用全尺寸索引。考虑到这一点,功能性指数不太可能有多大好处。即使在以下查询中:

SELECT ...
FROM "user"
WHERE left(hash, 20) = left($1, 20) AND hash = $1 
如果您认为使用较小的索引首先进行快速检查是在节省时间,那么实际上,PostgreSQL很可能会忽略函数索引而选择完整索引,因为它更具选择性

我不完全清楚您想要实现什么,但是如果它使用部分索引或函数索引来实现唯一约束,您就不能这样做


另外,将
hash
存储为
bytea
,并使用索引表达式
left(hash,20)
。或者可能是10,如果您当前以每字节2个字符的十六进制表示形式存储。

如果
哈希
是哈希函数的结果,您是否考虑将其存储为
二进制
?它将使存储成本降低两倍。然后,您可以将它添加到
UNIQUE
索引中。@Num6,是的。但是它会带来从二进制到字符串来回转换的成本吗?如果
散列
是散列函数的结果,您是否考虑将其存储为
二进制
?它将使存储成本降低两倍。然后,您可以将它添加到
UNIQUE
索引中。@Num6,是的。但是它会带来从二进制到字符串的转换成本吗?谢谢兄弟。这正是我要找的答案。如果答案是正确的,通常会把它标记为正确。谢谢兄弟。这正是我要找的答案。如果答案是正确的,通常会将其标记为正确。