Received: from localhost (unknown [200.46.204.183]) by mail.postgresql.org (Postfix) with ESMTP id 74B7264FCBF for ; Mon, 1 Dec 2008 09:30:22 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 58795-08 for ; Mon, 1 Dec 2008 09:30:19 -0400 (AST) X-Greylist: delayed 00:06:38.812135 by SQLgrey-1.7.6 Received: from 15.mail-out.ovh.net (15.mail-out.ovh.net [91.121.27.217]) by mail.postgresql.org (Postfix) with SMTP id EAC1A64FC94 for ; Mon, 1 Dec 2008 09:30:18 -0400 (AST) Received: (qmail 14968 invoked by uid 503); 1 Dec 2008 13:23:37 -0000 Received: from b7.ovh.net (HELO mail405.ha.ovh.net) (213.186.33.57) by 15.mail-out.ovh.net with SMTP; 1 Dec 2008 13:23:37 -0000 Received: from b0.ovh.net (HELO queue-out) (213.186.33.50) by b0.ovh.net with SMTP; 1 Dec 2008 13:23:18 -0000 Received: from par69-8-88-161-102-87.fbx.proxad.net (HELO soyouz) (88.161.102.87) by ns0.ovh.net with SMTP; 1 Dec 2008 13:23:18 -0000 Date: Mon, 01 Dec 2008 14:24:38 +0100 To: tmp , pgsql-performance@postgresql.org Subject: Re: Query optimization From: PFC Content-Type: text/plain; format=flowed; delsp=yes; charset=utf-8 MIME-Version: 1.0 References: Content-Transfer-Encoding: 7bit Message-ID: In-Reply-To: User-Agent: Opera Mail/9.62 (Linux) X-Ovh-Tracer-Id: 16520892283333182997 X-Ovh-Remote: 88.161.102.87 (par69-8-88-161-102-87.fbx.proxad.net) X-Ovh-Local: 213.186.33.20 (ns0.ovh.net) X-Spam-Check: DONE|H 0.5/N X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=0 tagged_above=0 required=5 tests=none X-Spam-Level: X-Archive-Number: 200812/1 X-Sequence-Number: 32037 > I am struggeling with the following query which fetches a random subset > of 200 questions that matches certain tags within certain languages. > However, the query takes forever to evaluate, even though I have a > "limit 200" appended. Any ideas on how to optimize it? > > QUERY: ================================================ > > SELECT distinct q.question_id > FROM question_tags qt, questions q > WHERE q.question_id = qt.question_id > AND q.STATUS = 1 > AND not q.author_id = 105 > AND ((qt.language_id = 5 and qt.tag_id in > (1101,917,734,550,367,183)) or (qt.language_id = 4 and qt.tag_id in > (856,428)) or (qt.language_id = > 3 and qt.tag_id in (1156,1028,899,771,642,514,385,257,128)) or > (qt.language_id = 2 and qt.tag_id in > (1193,1101,1009,917,826,734,642,550,458,367,275,183,91))) > and q.question_id not in (413) > LIMIT 200 > > EXPLAIN ANALYZE: ========================================= > > Limit (cost=1.50..1267.27 rows=200 width=4) (actual > time=278.169..880.934 rows=200 loops=1) > -> Unique (cost=1.50..317614.50 rows=50185 width=4) (actual > time=278.165..880.843 rows=200 loops=1) > -> Merge Join (cost=1.50..317489.04 rows=50185 width=4) > (actual time=278.162..880.579 rows=441 loops=1) > Merge Cond: (qt.question_id = q.question_id) > -> Index Scan using question_tags_question_id on > question_tags qt (cost=0.00..301256.96 rows=82051 width=4) (actual > time=24.171..146.811 rows=6067 loops=1) > Filter: (((language_id = 5) AND (tag_id = ANY > ('{1101,917,734,550,367,183}'::integer[]))) OR ((language_id = 4) AND > (tag_id = ANY ('{856,428}'::integer[]))) OR ((language_id = 3) AND > (tag_id = ANY ('{1156,1028,899,771,642,514,385,257,128}'::integer[]))) > OR ((language_id = 2) AND (tag_id = ANY > ('{1193,1101,1009,917,826,734,642,550,458,367,275,183,91}'::integer[])))) > -> Index Scan using questions_pkey on questions q > (cost=0.00..15464.12 rows=83488 width=4) (actual time=222.956..731.737 > rows=1000 loops=1) > Filter: ((q.author_id <> 105) AND (q.question_id > <> 413) AND (q.status = 1)) > Total runtime: 881.152 ms > (9 rows) An index on (language_id,tag_id) should be the first thing to try. Or perhaps even (status,language_id,tag_id) or (language_id, tad_id, status) (but that depends on the stats on "status" column). An index on author_id will probably not be useful for this particular query because your condition is "author_id != constant". Also CLUSTER question_tags on (language_id, tad_id). What is the database size versus RAM ? You must have a hell of a lot of questions to make this slow... (or bloat ?)