I have a PostgreSQL 9.3 table with multiple expression indexes defined. When I use explain
to see which indexes are being used for my query, I am surprised to see that PostgreSQL is not using the index which most closely-matches the conditions in my WHERE clause. It appears to be a problem specific to expression indexes. Here is a sqlfiddle link which demonstrates the problem:
http://sqlfiddle.com/#!15/580e0/1
CREATE TABLE Table1
("a" int, "b" int, "c" int, "d" int)
;
CREATE index a ON Table1 (a);
CREATE index ab ON Table1 (a,b);
CREATE index bplus1 ON Table1 ((b+1));
CREATE index abplus1 ON Table1 ((a+1),(b+1));
The basic multi-column index ab
is being used properly:
explain select * from Table1 where a = 1 AND b = 1
| QUERY PLAN |
|------------------------------------------------------------------|
| Index Scan using ab on table1 (cost=0.13..8.15 rows=1 width=16) |
| Index Cond: ((a = 1) AND (b = 1)) |
However the similar multi-column expression index abplus1 isn't being used:
explain select * from Table1 where (a+1) = 2 AND (b+1) = 2
| QUERY PLAN |
|----------------------------------------------------------------------|
| Index Scan using bplus1 on table1 (cost=0.13..8.16 rows=1 width=16) |
| Index Cond: ((b + 1) = 2) |
| Filter: ((a + 1) = 2) |
The strange thing is that the more-specific index does get used if the single-column expression indexes are removed. See this example http://sqlfiddle.com/#!15/f4fda/1:
explain select * from Table1 where (a+1) = 2 AND (b+1) = 2
| QUERY PLAN |
|-----------------------------------------------------------------------|
| Index Scan using abplus1 on table1 (cost=0.14..8.15 rows=1 width=16) |
| Index Cond: (((a + 1) = 2) AND ((b + 1) = 2)) |
It looks to me like there is a conflict between the single-expression and the multi-expression indexes. The surprising thing is that there doesn't appear to be any such conflict when using basic (non-expression) indexes.
Is there anything that I can do to work around this problem? I would like to keep both of my expression indexes, as each one is well-suited for particular queries.