I've been Googling for SQL tuning help for Postgres but the pickings have been rather slim. Maybe I'm using the wrong search terms. I'm trying to improve the performance of the following query and would be grateful for any hints, either directly on the problem at hand, or to resources I can read to find out more about how to do this. In the past I have fixed most problems by adding indexes to get rid of sequential scans, but in this case it appears to be the hash join and the nested loops that are taking up all the time and I don't really know what to do about that. In Google I found mostly references from people wanting to use a hash join to *fix* a performance problem, not deal with it creating one...

My Postgres version is 8.3.3, on Linux.

Thanks in advance,

janine

iso=# explain analyze select  a.item_id,
iso-#
iso-# content_item__get_best_revision(a.item_id) as revision_id, iso-# content_item__get_latest_revision(a.item_id) as last_revision_id, iso-# content_revision__get_number(a.article_id) as revision_no, iso-# (select count(*) from cr_revisions where item_id=a.item_id) as revision_count,
iso-#
iso-#                             -- Language support
iso-#                             b.lang_id,
iso-#                             b.lang_key,
iso-# (case when b.lang_key = 'big5' then '#D7D7D7' else '#ffffff' end) as tr_bgcolor, iso-# coalesce(dg21_item_langs__rel_lang (b.lang_id,'gb2312'),'0') as gb_item_id, iso-# coalesce(dg21_item_langs__rel_lang (b.lang_id,'iso-8859-1'),'0') as eng_item_id,
iso-#
iso-#                             -- user defined data
iso-#                             a.article_id,
iso-#                             a.region_id,
iso-#                             a.author,
iso-#                             a.archive_status,
iso-#                             a.article_status,
iso-#                             case when a.archive_status='t'
iso-# then '<font color=#808080>never expire</font>' iso-# else to_char(a.archive_date, 'YYYY年MM月DD日')
iso-#                             end as archive_date,
iso-#
iso-#                             -- Standard data
iso-#                             a.article_title,
iso-#                             a.article_desc,
iso-#                             a.creation_user,
iso-#                             a.creation_ip,
iso-#                             a.modifying_user,
iso-#
iso-#                             -- Pretty format data
iso-#                             a.item_creator,
iso-#
iso-#                             -- Other data
iso-#                             a.live_revision,
iso-# to_char(a.publish_date, 'YYYY年MM月 DD日') as publish_date, iso-# to_char(a.creation_date, 'DD/MM/YYYY HH:MI AM') as creation_date,
iso-#
iso-#                             case when article_status='approved'
iso-# then 'admin content, auto approved'
iso-#                                  when article_status='unapproved'
iso-#                                  then (select approval_text
iso(#                                        from   dg21_approval
iso(# where revision_id=a.article_id iso(# and approval_status='f' order by approval_date desc limit 1)
iso-#                                  else  ''
iso-#                             end as approval_text
iso-#
iso-# from dg21_article_items a, dg21_item_langs b
iso-#                     where   a.item_id = b.item_id
iso-#
iso-#                     order by b.lang_id desc, a.item_id
iso-#                     limit 21 offset 0;

QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=3516.97..3516.98 rows=1 width=1245) (actual time=195948.132..195948.250 rows=21 loops=1) -> Sort (cost=3516.97..3516.98 rows=1 width=1245) (actual time=195948.122..195948.165 rows=21 loops=1)
         Sort Key: b.lang_id, ci.item_id
         Sort Method:  top-N heapsort  Memory: 24kB
-> Nested Loop (cost=719.67..3516.96 rows=1 width=1245) (actual time=346.687..195852.741 rows=4159 loops=1) -> Nested Loop (cost=719.67..3199.40 rows=1 width=413) (actual time=311.422..119467.334 rows=4159 loops=1) -> Nested Loop (cost=719.67..3198.86 rows=1 width=400) (actual time=292.951..1811.051 rows=4159 loops=1) -> Hash Join (cost=719.67..3197.98 rows=1 width=352) (actual time=292.832..777.290 rows=4159 loops=1)
                                 Hash Cond: (cr.item_id = ci.item_id)
Join Filter: ((ci.live_revision = cr.revision_id) OR ((ci.live_revision IS NULL) AND (cr.revision_id = content_item__get_latest_revision(ci.item_id)))) -> Hash Join (cost=154.38..1265.24 rows=4950 width=348) (actual time=74.789..375.580 rows=4950 loops=1) Hash Cond: (cr.revision_id = ox.article_id) -> Seq Scan on cr_revisions cr (cost=0.00..913.73 rows=16873 width=321) (actual time=0.058..71.539 rows=16873 loops=1) -> Hash (cost=92.50..92.50 rows=4950 width=27) (actual time=74.607..74.607 rows=4950 loops=1) -> Seq Scan on dg21_articles ox (cost=0.00..92.50 rows=4950 width=27) (actual time=0.071..18.604 rows=4950 loops=1) -> Hash (cost=384.02..384.02 rows=14502 width=8) (actual time=217.789..217.789 rows=14502 loops=1) -> Seq Scan on cr_items ci (cost=0.00..384.02 rows=14502 width=8) (actual time=0.051..137.988 rows=14502 loops=1) -> Index Scan using acs_objects_pk on acs_objects ao (cost=0.00..0.88 rows=1 width=56) (actual time=0.223..0.229 rows=1 loops=4159) Index Cond: (ao.object_id = cr.revision_id) -> Index Scan using persons_pk on persons ps (cost=0.00..0.27 rows=1 width=17) (actual time=0.017..0.023 rows=1 loops=4159) Index Cond: (ps.person_id = ao.creation_user) -> Index Scan using dg21_item_langs_id_key on dg21_item_langs b (cost=0.00..8.27 rows=1 width=15) (actual time=0.526..0.537 rows=1 loops=4159)
                     Index Cond: (b.item_id = ci.item_id)
               SubPlan
-> Limit (cost=297.21..297.22 rows=1 width=29) (never executed) -> Sort (cost=297.21..297.22 rows=1 width=29) (never executed)
                             Sort Key: dg21_approval.approval_date
-> Seq Scan on dg21_approval (cost=0.00..297.20 rows=1 width=29) (never executed) Filter: ((revision_id = $2) AND ((approval_status)::text = 'f'::text)) -> Aggregate (cost=10.77..10.78 rows=1 width=0) (actual time=0.051..0.053 rows=1 loops=4159) -> Index Scan using cr_revisions_item_id_idx on cr_revisions (cost=0.00..10.77 rows=2 width=0) (actual time=0.019..0.024 rows=1 loops=4159)
                             Index Cond: (item_id = $0)
 Total runtime: 195949.928 ms
(33 rows)

---
Janine Sisk
President/CEO of furfly, LLC
503-693-6407





--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance

Reply via email to