@Edward_Ribbery Indeed, partial indexes are supported.
Here is an example using a (unique) index on a jsonb
attribute (which may be missing/null).
Note: for compatibility reasons our default database is also called postgres.
Start cluster and connect (if needed)
./bin/yb-ctl start
./bin/ysqlsh
Create table and index.
postgres=# CREATE TABLE test(i int PRIMARY KEY, j jsonb);
CREATE TABLE
postgres=# CREATE UNIQUE index json_attr_idx ON test((j->>'k1')) WHERE j->>'k1' IS NOT NULL;
CREATE INDEX
Now we insert some values.
postgres=# INSERT INTO test(i, j) VALUES (1, '{"k0": "a1", "k1": "b1"}');
INSERT 0 1
postgres=# INSERT INTO test(i, j) VALUES (2, '{"k0": "a2", "k1": "b2"}');
INSERT 0 1
Insert a duplicate value (b1
already exists so uniqueness check should fail).
postgres=# INSERT INTO test(i, j) VALUES (3, '{"k0": "a1", "k1": "b1"}');
ERROR: duplicate key value violates unique constraint "json_attr_idx"
Insert a couple of NULLs in the index (i.e. no value for that attribute).
postgres=# INSERT INTO test(i, j) VALUES (4, '{"k0": "a4"}');
INSERT 0 1
postgres=# INSERT INTO test(i, j) VALUES (5, '{"k0": "a5"}');
INSERT 0 1
A select with a matching condition will use the index.
postgres=# EXPLAIN SELECT * FROM test WHERE j->>'k1' = 'b1';
QUERY PLAN
------------------------------------------------------------------------------
Index Scan using json_attr_idx on test (cost=0.00..4.01 rows=1000 width=36)
Index Cond: ((j ->> 'k1'::text) = 'b1'::text)
(2 rows)
postgres=# SELECT * FROM test WHERE j->>'k1' = 'b1';
i | j
---+--------------------------
1 | {"k0": "a1", "k1": "b1"}
(1 row)
A select checking for null NULL
will do a table scan.
Note: We call this a “Foreign Scan” for historical reasons – we have a TODO to change it.
postgres=# EXPLAIN SELECT * FROM test WHERE j->>'k1' IS NULL;
QUERY PLAN
--------------------------------------------------------------
Foreign Scan on test (cost=0.00..102.50 rows=1000 width=36)
Filter: ((j ->> 'k1'::text) IS NULL)
(2 rows)
postgres=# SELECT * FROM test WHERE j->>'k1' IS NULL;
i | j
---+--------------
5 | {"k0": "a5"}
4 | {"k0": "a4"}
(2 rows)