Received: from localhost (unknown [200.46.204.183]) by postgresql.org (Postfix) with ESMTP id EF3706502CA for ; Tue, 26 Aug 2008 13:38:02 -0300 (ADT) Received: from postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 57971-01-9 for ; Tue, 26 Aug 2008 13:37:54 -0300 (ADT) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-gx0-f17.google.com (mail-gx0-f17.google.com [209.85.217.17]) by postgresql.org (Postfix) with ESMTP id 69DF06502F2 for ; Tue, 26 Aug 2008 13:37:33 -0300 (ADT) Received: by gxk10 with SMTP id 10so3428020gxk.19 for ; Tue, 26 Aug 2008 09:37:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:sender :to:subject:cc:mime-version:content-type:content-transfer-encoding :content-disposition:x-google-sender-auth; bh=9JM1Z+ix36yW+5tfSNDS/wSqfmMgsi/Bqk/2+eo5MAM=; b=TYdh8BL5xKpT0iRAp9YlxnfDo6z5oJbKJUFjc3Yec6k8S3HRIO4LS8eqLnZDAQN3/7 b5Kdc9rnsCZMt9O7uJli9CgZsTE9aRhANvNxjixHBHfo5N9zIsoELVnSEHBRVPXfUxuq onzDgN5Sa/5j9Vw0TrvstbgGKYv1E5mFvpeJc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:sender:to:subject:cc:mime-version:content-type :content-transfer-encoding:content-disposition:x-google-sender-auth; b=BlF3DUY/Z8ouHghpg7Z9z6Q+bz67f1R24LwYl77smEYfhmmo9mUmNfSq11GI5D+c9y gsEkizPTrTEIlcKfUbqYVUjRZtsalyZWleixUlXW+HllxqVjDYinz4eVC7+WE+Uu2QO8 pNQgDN3oej9NpvWcWopeI3pnuikVO3Ibn+Trs= Received: by 10.150.192.7 with SMTP id p7mr9494056ybf.158.1219768652626; Tue, 26 Aug 2008 09:37:32 -0700 (PDT) Received: by 10.151.45.8 with HTTP; Tue, 26 Aug 2008 09:37:32 -0700 (PDT) Message-ID: <7d10d2df0808260937v3103e216h764bbb74ca597d6f@mail.gmail.com> Date: Tue, 26 Aug 2008 17:37:32 +0100 From: "Frank Joerdens" To: pgsql-performance@postgresql.org Subject: Query w empty result set with LIMIT orders of magnitude slower than without Cc: Nic , "Seb Potter" MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline X-Google-Sender-Auth: b6b41e7bbbca5d1d 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: 200808/330 X-Sequence-Number: 31211 It seems to me that the planner makes a very poor decision with this particular query: --- snip --- woome=> explain analyze SELECT "webapp_invite"."id", "webapp_invite"."person_id", "webapp_invite"."session_id", "webapp_invite"."created", "webapp_invite"."text", "webapp_invite"."subject", "webapp_invite"."email", "webapp_invite"."batch_seen", "webapp_invite"."woouser", "webapp_invite"."accepted", "webapp_invite"."declined", "webapp_invite"."deleted", "webapp_invite"."local_start_time" FROM "webapp_invite" INNER JOIN "webapp_person" ON ("webapp_invite"."person_id" = "webapp_person"."id") INNER JOIN "webapp_person" T3 ON ("webapp_invite"."person_id" = T3."id") WHERE "webapp_person"."is_suspended" = false AND T3."is_banned" = false AND "webapp_invite"."woouser" = 'suggus' ORDER BY "webapp_invite"."id" DESC LIMIT 5; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit (cost=0.00..3324.29 rows=5 width=44) (actual time=2545.137..2545.137 rows=0 loops=1) -> Nested Loop (cost=0.00..207435.61 rows=312 width=44) (actual time=2545.135..2545.135 rows=0 loops=1) -> Nested Loop (cost=0.00..204803.04 rows=322 width=48) (actual time=2545.133..2545.133 rows=0 loops=1) -> Index Scan Backward using webapp_invite_pkey on webapp_invite (cost=0.00..201698.51 rows=382 width=44) (actual time=2545.131..2545.131 rows=0 loops=1) Filter: ((woouser)::text = 'suggus'::text) -> Index Scan using webapp_person_pkey on webapp_person t3 (cost=0.00..8.11 rows=1 width=4) (never executed) Index Cond: (t3.id = webapp_invite.person_id) Filter: (NOT t3.is_banned) -> Index Scan using webapp_person_pkey on webapp_person (cost=0.00..8.16 rows=1 width=4) (never executed) Index Cond: (webapp_person.id = webapp_invite.person_id) Filter: (NOT webapp_person.is_suspended) Total runtime: 2545.284 ms (12 rows) --- snap --- because if I just remove the LIMIT, it runs like the wind: --- snip --- woome=> explain analyze SELECT "webapp_invite"."id", "webapp_invite"."person_id", "webapp_invite"."session_id", "webapp_invite"."created", "webapp_invite"."text", "webapp_invite"."subject", "webapp_invite"."email", "webapp_invite"."batch_seen", "webapp_invite"."woouser", "webapp_invite"."accepted", "webapp_invite"."declined", "webapp_invite"."deleted", "webapp_invite"."local_start_time" FROM "webapp_invite" INNER JOIN "webapp_person" ON ("webapp_invite"."person_id" = "webapp_person"."id") INNER JOIN "webapp_person" T3 ON ("webapp_invite"."person_id" = T3."id") WHERE "webapp_person"."is_suspended" = false AND T3."is_banned" = false AND "webapp_invite"."woouser" = 'suggus' ORDER BY "webapp_invite"."id" DESC; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- Sort (cost=7194.46..7195.24 rows=312 width=44) (actual time=0.141..0.141 rows=0 loops=1) Sort Key: webapp_invite.id Sort Method: quicksort Memory: 25kB -> Nested Loop (cost=12.20..7181.53 rows=312 width=44) (actual time=0.087..0.087 rows=0 loops=1) -> Nested Loop (cost=12.20..4548.96 rows=322 width=48) (actual time=0.085..0.085 rows=0 loops=1) -> Bitmap Heap Scan on webapp_invite (cost=12.20..1444.44 rows=382 width=44) (actual time=0.084..0.084 rows=0 loops=1) Recheck Cond: ((woouser)::text = 'suggus'::text) -> Bitmap Index Scan on webapp_invite_woouser_idx (cost=0.00..12.10 rows=382 width=0) (actual time=0.081..0.081 rows=0 loops=1) Index Cond: ((woouser)::text = 'suggus'::text) -> Index Scan using webapp_person_pkey on webapp_person t3 (cost=0.00..8.11 rows=1 width=4) (never executed) Index Cond: (t3.id = webapp_invite.person_id) Filter: (NOT t3.is_banned) -> Index Scan using webapp_person_pkey on webapp_person (cost=0.00..8.16 rows=1 width=4) (never executed) Index Cond: (webapp_person.id = webapp_invite.person_id) Filter: (NOT webapp_person.is_suspended) Total runtime: 0.295 ms (16 rows) --- snap --- And for this particular filter, the result set is empty to boot, so the LIMIT doesn't even do anything. Does this behaviour make sense to anyone? Can I force the planner somehow to be smarter about it? Thanks! Frank