I created a bloom index, and it turns out that PostgreSQL's query planner just doesn't want to use the index for boolean.
Here is my test setup:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS bloom;
-- Adapt bloom index to boolean type
DROP OPERATOR CLASS IF EXISTS bloom_boolean_ops USING bloom;
CREATE OPERATOR CLASS bloom_boolean_ops
DEFAULT FOR TYPE boolean USING bloom AS
OPERATOR 1 = (boolean, boolean),
FUNCTION 1 hashchar;
-- Do the same, but for uuid type
-- This is needed to just demonstrate that this way of defining custom operator classes
-- works for other types, but doesn't work for boolean.
DROP OPERATOR CLASS IF EXISTS bloom_uuid_ops USING bloom;
CREATE OPERATOR CLASS bloom_uuid_ops
DEFAULT FOR TYPE uuid USING bloom AS
OPERATOR 1 = (uuid, uuid),
FUNCTION 1 uuid_hash;
CREATE TABLE test_tbl (
id uuid NOT NULL,
flag boolean NOT NULL
);
INSERT INTO test_tbl (id, flag) VALUES
('e5526344-669c-46ba-aece-8fbc82007161', true),
('b25aefdf-2aba-4e5a-83c3-ec2da3b934ac', false);
CREATE INDEX test_bloom_idx ON test_tbl USING bloom (flag, id);
SET ENABLE_SEQSCAN = OFF;
-- Try the boolean column. For some reason, the query planner ignores the index.
EXPLAIN SELECT 1 FROM test_tbl WHERE flag = TRUE;
-- Seq Scan on test_tbl (cost=10000000000.00..10000000001.02 rows=1 width=4)
-- Filter: flag
-- Try the uuid column. Now it works fine.
EXPLAIN SELECT 1 FROM test_tbl WHERE id = 'e5526344-669c-46ba-aece-8fbc82007161';
-- Bitmap Heap Scan on test_tbl (cost=8.02..12.03 rows=1 width=4)
-- Recheck Cond: (id = 'e5526344-669c-46ba-aece-8fbc82007161'::uuid)
-- -> Bitmap Index Scan on test_bloom_idx (cost=0.00..8.02 rows=1 width=0)
-- Index Cond: (id = 'e5526344-669c-46ba-aece-8fbc82007161'::uuid)
So as illustrated above, the query planner chooses to use index for searching uuid, but it just ignores it if the column happens to be boolean.
Also boolean expression indexes (like CREATE INDEX ... ((column = value));) are broken in the same way.
I've already tried:
- Split a multi-column index to individual single-column indexes (although it doesn't make make a lot of sense with bloom).
- Cast
booleantointeger. It works, but queries are not friendly to the ORM that I use. So this is not an option for me. - Use different hash functions:
hashint2,hashint4,hashchar("char")for the operator class. No effect.
Any suggestions?
(and yeah, I'm aware of partial indexes, they are not quite what I want)