Re: [GENERAL] Question about partial functional indexes and the query planner

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Brian Dunavant <brian(at)omniti(dot)com>
Cc: pgsql-general(at)postgresql(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: [GENERAL] Question about partial functional indexes and the query planner
Date: 2014-06-10 23:19:36
Message-ID: 7708.1402442376@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general pgsql-hackers

Brian Dunavant <brian(at)omniti(dot)com> writes:
> I am using a partial functional index on a table where F(a) = a. Querying
> whre F(a) = a hits the index as expected. However the reverse statement a
> = F(a) does not. I have verified this in 9.3.4.
> Is this a deficiency with the query planner, or are these not actually
> equivalent? I've been stumped on it.

Interesting. The reason this doesn't work is that predicate_implied_by()
fails to prove "a = b" given "b = a", at least in the general case.
It will figure that out if either a or b is a constant, but not if
neither one is. The fact that it works with constants might explain
the lack of previous complaints, but this is still pretty surprising
given the amount of knowledge about equality that the system evinces
otherwise. (I'm also wondering whether the EquivalenceClass logic
might not sometimes rewrite "a = b" into "b = a", causing a failure
of this sort even when the user *had* phrased his query consistently.)

It would be fairly straightforward to add a proof rule along the lines of
"if both expressions are binary opclauses, and the left input expression
of each one is equal() to the right input of the other, and the operators
are each other's commutators, then the implication holds".

An objection might be made that this would add noticeably to the cost of
failing proofs, but I think it wouldn't be that bad, especially if we did
the syscache lookup for the commutator check last. In most scenarios the
equal() checks would fail pretty quickly when the proof rule doesn't
apply. Also, I believe that in the case where a or b is a constant,
even though we can make the proof already, this approach would succeed
noticeably more quickly than btree_predicate_proof() can. (Worth noting
also is that predicate_implied_by() isn't even used unless you have
things like partial indexes involved, so that its cost is not especially
relevant to "simple" queries.)

I'd be inclined to add some similar proof rules to predicate_refuted_by,
along the lines of "a op1 b refutes a op2 b if op1 is op2's negator" and
"a op1 b refutes b op2 a if op1 is the negator of op2's commutator".
Again, the code is currently unable to make such deductions unless a or b
is a constant.

Given the lack of previous complaints, I'm not sure this amounts to
a back-patchable bug, but it does seem like something worth fixing
going forward.

regards, tom lane

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Raimo Jormakka 2014-06-11 06:20:55 Accessing structured datatypes using libpq
Previous Message Brian Dunavant 2014-06-10 21:29:13 Question about partial functional indexes and the query planner

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2014-06-10 23:24:11 Re: API change advice: Passing plan invalidation info from the rewriter into the planner?
Previous Message Craig Ringer 2014-06-10 23:18:39 Re: API change advice: Passing plan invalidation info from the rewriter into the planner?