18

With Postgres 10 properly supporting hash index, I would like to use hash index for id lookup (hash index is smaller in size compared to btree and theoretically faster).

I have a table

create table t (id int);
create unique index on t using hash (id);

But I got the following:

ERROR: access method "hash" does not support unique indexes

Why does hash index not allow unique constraint? Are there ways to circumvent this?

4 Answers 4

19

The documentation leaves no room for doubt:

Currently, only B-tree indexes can be declared unique.

There was a discussion on the hackers list about this recently, and it was concluded that it wouldn't be simple to add the capability to allow UNIQUE hash indexes.

Sign up to request clarification or add additional context in comments.

Comments

9

You can achieve this using an exclusion constraint:

create table t (id int);
alter table t add constraint c exclude using hash (id with =);

10 Comments

Would you know how the size would compare with the unique index? I'm assuming it would be less but have you checked? Also do you know how the exclusion index would perform on a billion rows?
@jbg how did you do upsert? I have a trouble with syntax conn.execute( f"""INSERT INTO {TABLE_NAME} VALUES ($1, $2) ON CONFLICT (id) DO UPDATE SET value = ($2)""", hash_id, str_profile, ) gives me there is no unique or exclusion constraint matching the ON CONFLICT specification
@LukaszMadon Name the constraint in the ON CONFLICT clause instead of making Postgres infer it from the column (which only works with unique indexes, not with exclusion constraints). In the example in my answer it would be ON CONFLICT (c) DO .... See the docs: postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT
thanks for the reply, I came to the same conclusion. ON CONFLICT ON CONSTRAINT cnp_profiles_id_excl DO UPDATE which results in WrongObjectTypeError: ON CONFLICT DO UPDATE not supported with exclusion constraints I can't use hash indexes with this kind of upserts.
The create index command isn't needed - the constraint creation already creates an index.
|
-1

why not just simply add a constraint for this column ?

create table t (id int);
create index on t using hash (id);

-- simply create a new constraint for this column, do not mix it with hash index
alter table t add constraint unique_id unique (id); 

1 Comment

Because constraint would create btree index. In case of long (about 3k) strings, btree would fail!
-1

Very old idea

create unique index on links (cast(md5(url) as uuid));

I'm trying it now

UPD. It's slow like it's recalculating every sum on every insert.

UPD2. Adding functional unique index does not speed up SEARCH on the column.

To find the string in question one should either search by the same cast or add a hash index.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.