We bottom (or inline) post on these lists.

On Tue, Mar 8, 2016 at 3:37 PM, Adam Brusselback <adambrusselb...@gmail.com>
wrote:

> ​
> On Tue, Mar 8, 2016 at 5:17 PM, Tom Lane <t...@sss.pgh.pa.us> wrote:
>
>> Adam Brusselback <adambrusselb...@gmail.com> writes:
>> > I was wondering if there were any plans to support predicate push-down
>> > optimization for subqueries (and views) with aggregates?
>>
>> Right offhand I would say that that's a complete mischaracterization
>> of the problem.  I've not tried to run your test case, but you say
>>
>> > --Quick, is able to push down because it's a simple equality check
>> > SELECT *
>> > FROM header
>> > INNER JOIN header_total
>> > USING (header_id)
>> > WHERE header.header_id = 26;
>> >
>> > --Slow, no pushdown
>> > SELECT *
>> > FROM header
>> > INNER JOIN header_total
>> > USING (header_id)
>> > WHERE header.header_id < 200;
>> >
>> > --Slow, no pushdown
>> > SELECT *
>> > FROM header
>> > INNER JOIN header_total
>> > USING (header_id)
>> > WHERE header.description like '%5%';
>>
>> There's no preference for equalities over other kinds of predicates
>> as far as subquery pushdown is concerned.  I think what your real
>> problem is is that in the first case, the system will derive the
>> additional condition "header_total.header_id = 26", while in the
>> second case it will not deduce "header_total.header_id < 200".
>> That's because the machinery for deducing such implied constraints
>> works only with equalities.  That's not very likely to change anytime
>> soon, and even if it did, the inference would only extend to operators
>> that are members of the same btree family as the join equality operator.
>> Your example with a LIKE clause is always going to be out in the cold,
>> because there is no principled basis for the planner to decide that
>> "a = b" means that "a LIKE x" and "b LIKE x" will give the same result.
>> It hasn't got enough information about the behavior of LIKE to know
>> if that's safe or not.  (It does, on the other hand, know very well that
>> SQL equality operators don't necessarily guarantee bitwise identity.)
>>
>> So I'd suggest just modifying your queries to write out both constraints
>> explicitly.
>>
>> ​
>> ​
>> Thanks Tom, appreciate the reply.
>>
>
> Sorry if I didn't call it the correct thing. I just know that with trying
> to encapsulate this aggregate logic in a view, I am unable to use that view
> in a query that I know is only going to touch a subset of the data without
> incurring a performance hit from the view doing seq scans on all of the
> rows in the detail_1 and detail_2 tables, and then throwing out 99% of the
> results when the filter is applied.
>
> I had initially started creating functions that would take an array of ids
> as a parameter, and manually push them down in the subqueries.  That got
> really really messy though, and we moved away from doing that to having the
> aggregates eagerly materialized to a table with triggers.
>
>
> Are there any other options for making this type of query faster?  It
> could be that I just am totally missing a better way to do this.  I do
> really want to be able to contain that logic within a view of some sort
> though, as a bunch of other stuff is built on top of that.  Having to push
> that aggregate query into all of those other queries would be hell.
>
>
​Maybe something like:

CREATE TYPE header_total_item (
     amount numeric,
     count    integer
)​;

CREATE VIEW AS
SELECT header_id, header_amount
COALESCE(
(SELECT ROW(sum(rate * quantity), count(detail_1_id))::header_total_item
FROM detail_1 WHERE detail_1.header_id = header.header_id)
ROW(0.000,0)::header_total_item
) AS detail_1_total_item
FROM header;

​​Doesn't solve the "balance" column without going into a sub-query...which
I suspect is possible but don't have time to test.

I do understand the question as to why the view cannot be re-written as:

I don't have time to get into this deeper right now.  The main question is
basically how can you force a parameterized nested join on the LEFT JOIN
sub-queries given that the system has equality joins between them and
header and you've supposedly provided a very selective predicate for the
rows being returned by header.

David J.

Reply via email to