Re: Help with tuning this query - Mailing list pgsql-performance

From John Arbash Meinel
Subject Re: Help with tuning this query
Date
Msg-id 4225F04F.6060305@arbash-meinel.com
Whole thread Raw
In response to Help with tuning this query  ("Ken Egervari" <ken@upfactor.com>)
List pgsql-performance
Ken Egervari wrote:

> I've tried to use Dan Tow's tuning method and created all the right
> indexes from his diagraming method, but the query still performs quite
> slow both inside the application and just inside pgadmin III.  Can
> anyone be kind enough to help me tune it so that it performs better in
> postgres?  I don't think it's using the right indexes, or maybe
> postgres needs special treatment.
>

First, what version of postgres, and have you run VACUUM ANALYZE recently?
Also, please attach the result of running EXPLAIN ANALYZE.
(eg, explain analyze select s.* from shipment ...)

It's very possible that you don't have up-to-date statistics, which
causes postgres to make a bad estimate of what the fastest plan is.

Also, if you are using an older version of postgres (like 7.1) you
really should upgrade. There are quite a few performance and real bug fixes.

> I've converted the below query to SQL from a Hibernate query, so the
> syntax is probably not perfect but it's semantics are exactly the
> same.  I've done so by looking at the source code, but I can't run it
> to get the exact SQL since I don't have the database on my home machine.

I don't know how to make Hibernate do what you want, but if you change
the query to using subselects (not all databases support this, so
hibernate might not let you), you can see a performance improvement.
Also sometimes using explicit joins can be worse than just letting the
query manager figure it out. So something like
select s.* from shipment s, carrier_code cc, carrier c, ...
    where s.carrier_code_id = cc.id and c.id = cc.carrier_id and ....

But again, since this is generated from another program (Hibernate), I
really don't know how you tell it how to tune the SQL. Probably the
biggest "non-bug" performance improvements are from tuning the SQL.
But if postgres isn't using the right indexes, etc, you can probably fix
that.

John
=:->

>
> select s.*
> from shipment s
>     inner join carrier_code cc on s.carrier_code_id = cc.id
>     inner join carrier c on cc.carrier_id = c.id
>     inner join carrier_to_person ctp on ctp.carrier_id = c.id
>     inner join person p on p.id = ctp.person_id
>     inner join shipment_status cs on s.current_status_id = cs.id
>     inner join release_code rc on cs.release_code_id = rc.id
>     left join shipment_status ss on ss.shipment_id = s.id
> where
>     p.id = :personId and
>     s.is_purged = false and
>     rc.number = '9' and
>     cs is not null and
>     cs.date >= current_date - 31
> order by cs.date desc
> Just assume I have no indexes for the moment because while some of the
> indexes I made make it work faster, it's still around 250 milliseconds
> and under heavy load, the query performs very badly (6-7 seconds).
>
> For your information:
>
> shipment contains 40,000 rows
> shipment_status contains 80,000 rows
> release_code contains 8 rows
> person contains 300 rows
> carrier contains 60 rows
> carrier_code contains 70 rows
>
> The filter ratios are:
>
> rc.number = '9' (0.125)
> cs.date >= current_date - 31 (.10)
> p.id = ? (0.003)
> s.is_purged = false (.98)
>
> I really hope someone can help since I'm pretty much stuck.
>
> Best regards and many thanks,
> Ken



Attachment

pgsql-performance by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: Help with tuning this query
Next
From: "Ken Egervari"
Date:
Subject: Re: Help with tuning this query