X-Original-To: pgsql-performance-postgresql.org@localhost.postgresql.org Received: from localhost (av.hub.org [200.46.204.144]) by postgresql.org (Postfix) with ESMTP id CAE369DC813 for ; Wed, 21 Dec 2005 02:55:27 -0400 (AST) Received: from postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 82934-02 for ; Wed, 21 Dec 2005 02:55:27 -0400 (AST) X-Greylist: from auto-whitelisted by SQLgrey- Received: from linda-1.paradise.net.nz (bm-1a.paradise.net.nz [203.96.152.180]) by postgresql.org (Postfix) with ESMTP id 355FB9DC80C for ; Wed, 21 Dec 2005 02:55:24 -0400 (AST) Received: from smtp-2.paradise.net.nz (tclsnelb1-src-1.paradise.net.nz [203.96.152.172]) by linda-1.paradise.net.nz (Paradise.net.nz) with ESMTP id <0IRU00AHA5WC15@linda-1.paradise.net.nz> for pgsql-performance@postgresql.org; Wed, 21 Dec 2005 19:55:24 +1300 (NZDT) Received: from [192.168.1.11] (218-101-28-211.dsl.clear.net.nz [218.101.28.211]) by smtp-2.paradise.net.nz (Postfix) with ESMTP id F08471525DDD; Wed, 21 Dec 2005 19:55:23 +1300 (NZDT) Date: Wed, 21 Dec 2005 19:55:20 +1300 From: Mark Kirkwood Subject: Re: Simple Join In-reply-to: <43A0AB0A.3000403@paradise.net.nz> To: Kevin Brown Cc: pgsql-performance@postgresql.org Message-id: <43A8FC58.1020609@paradise.net.nz> MIME-version: 1.0 Content-type: text/plain; format=flowed; charset=ISO-8859-1 Content-transfer-encoding: 7bit X-Accept-Language: en-us, en User-Agent: Mozilla Thunderbird 1.0.6 (X11/20051106) References: <200512141603.52583.blargity@gmail.com> <43A0AB0A.3000403@paradise.net.nz> X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, score=0.341 required=5 tests=[AWL=0.341] X-Spam-Score: 0.341 X-Spam-Level: X-Archive-Number: 200512/526 X-Sequence-Number: 16347 Mark Kirkwood wrote: > Kevin Brown wrote: > >> I'll just start by warning that I'm new-ish to postgresql. >> >> I'm running 8.1 installed from source on a Debian Sarge server. I >> have a simple query that I believe I've placed the indexes correctly >> for, and I still end up with a seq scan. It makes sense, kinda, but >> it should be able to use the index to gather the right values. I do >> have a production set of data inserted into the tables, so this is >> running realistically: >> >> dli=# explain analyze SELECT ordered_products.product_id >> dli-# FROM to_ship, ordered_products >> dli-# WHERE to_ship.ordered_product_id = ordered_products.id AND >> dli-# ordered_products.paid = TRUE AND >> dli-# ordered_products.suspended_sub = FALSE; > > > You scan 600000 rows from to_ship to get about 25000 - so some way to > cut this down would help. > > Try out an explicit INNER JOIN which includes the filter info for paid > and suspended_sub in the join condition (you may need indexes on each of > id, paid and suspended_sub, so that the 8.1 optimizer can use a bitmap > scan): > > > SELECT ordered_products.product_id > FROM to_ship INNER JOIN ordered_products > ON (to_ship.ordered_product_id = ordered_products.id > AND ordered_products.paid = TRUE AND > ordered_products.suspended_sub = FALSE); It has been a quiet day today, so I took another look at this. If the selectivity of clauses : paid = TRUE suspended_sub = FALSE is fairly high, then rewriting as a subquery might help: SELECT o.product_id FROM ordered_products o WHERE o.paid = TRUE AND o.suspended_sub = FALSE AND EXISTS ( SELECT 1 FROM to_ship s WHERE s.ordered_product_id = o.id ); However it depends on you not needing anything from to_ship in the SELECT list... Cheers Mark