Multi-expression indexes in PostgreSQL not using being used as expected
It looks to me like there is a conflict between the single-expression and the multi-expression indexes.


All applicable indexes are candidates, if that's what you mean by "conflict". But that's the extent of it. Postgres estimates execution time based on table and index statistics in combination with cost settings, and the best estimate wins.

If Postgres expects one of your two conditions to be selective enough, it will likely take a matching single-column index and filter possible (few!) false positives in a FILTER step with the second condition.

However, that is certainly not the case for the data distribution you mention in the comment:


  20,000 rows. b=1 for 10,000, a=1 for 2. One row for a=1,b=1


@ypercube already demonstrated in his sqlfiddle that your test should use the multicolumn index. Even more so with the data distribution you describe.

If you provide the output of EXPLAIN (ANALYZE, BUFFERS) instead of just EXPLAIN, we might be able to see more. I would guess you didn't run ANALYZE after creating the expression index, which is required to update statistics.  autovacuum will kick in after some time, but not fast enough if you run your test immediately after creating the index (and never for temporary tables!).

ANALYZE Table1;


Come to think of it, we (that is: you &amp; me) solved this problem before:


PostgreSQL partial index unused when created on a table with existing data


Also related:


Index that is not used, yet influences query


That aside, Postgres 9.3 is getting old. There have been 3 major release since. If you run into problems like this I suggest to test a current version and see if the problem is still there.