Received: from localhost (unknown [200.46.208.211]) by mail.postgresql.org (Postfix) with ESMTP id 13F2A633C0F for ; Tue, 18 Aug 2009 17:00:29 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.208.211]) (amavisd-maia, port 10024) with ESMTP id 66542-06 for ; Tue, 18 Aug 2009 20:00:14 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from FS.denninger.net (wsip-70-169-168-7.pn.at.cox.net [70.169.168.7]) by mail.postgresql.org (Postfix) with ESMTP id 5BDC8633A15 for ; Tue, 18 Aug 2009 17:00:17 -0300 (ADT) Received: from [127.0.0.1] (localhost [127.0.0.1]) by FS.denninger.net (8.14.3/8.13.1) with SMTP id n7IJkE1i052566 for ; Tue, 18 Aug 2009 14:46:14 -0500 (CDT) (envelope-from karl@denninger.net) Received: from [127.0.0.1] [192.168.1.40] by Spamblock-sys (LOCAL); Tue Aug 18 14:46:14 2009 Message-ID: <4A8B04C7.6060702@denninger.net> Date: Tue, 18 Aug 2009 14:45:11 -0500 From: Karl Denninger User-Agent: Thunderbird 2.0.0.22 (Windows/20090605) MIME-Version: 1.0 To: pgsql-sql@postgresql.org, pgsql-performance@postgresql.org Subject: SQL Query Performance - what gives? X-Enigmail-Version: 0.96.0 Content-Type: multipart/mixed; boundary="------------060708040808070501050806" X-Antivirus: avast! (VPS 090817-0, 08/17/2009), Outbound message X-Antivirus-Status: Clean X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-2.499 tagged_above=-10 required=5 tests=BAYES_00=-2.599, RDNS_DYNAMIC=0.1 X-Spam-Level: X-Archive-Number: 200908/193 X-Sequence-Number: 35225 This is a multi-part message in MIME format. --------------060708040808070501050806 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Let's take the following EXPLAIN results: ticker=# explain select * from post, forum where forum.name = post.forum and invisible <> 1 and to_tsvector('english', message) @@ to_tsquery('violence') order by modified desc limit 100; QUERY PLAN --------------------------------------------------------------------------------------------------------------- Limit (cost=5951.85..5952.10 rows=100 width=706) -> Sort (cost=5951.85..5955.37 rows=1408 width=706) Sort Key: post.modified -> Hash Join (cost=613.80..5898.04 rows=1408 width=706) Hash Cond: (post.forum = forum.name) -> Bitmap Heap Scan on post (cost=370.93..5635.71 rows=1435 width=435) Recheck Cond: (to_tsvector('english'::text, message) @@ to_tsquery('violence'::text)) Filter: (invisible <> 1) -> Bitmap Index Scan on idx_message (cost=0.00..370.57 rows=1435 width=0) Index Cond: (to_tsvector('english'::text, message) @@ to_tsquery('violence'::text)) -> Hash (cost=242.07..242.07 rows=64 width=271) -> Index Scan using forum_name on forum (cost=0.00..242.07 rows=64 width=271) (12 rows) ticker=# And ticker=# explain select * from post, forum where forum.name = post.forum and invisible <> 1 and ((permission & '127') = permission) and (contrib is null or contrib = ' ' or contrib like '%b%') and to_tsvector('english', message) @@ to_tsquery('violence') order by modified desc limit 100; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------ Limit (cost=1329.81..1329.87 rows=22 width=706) -> Sort (cost=1329.81..1329.87 rows=22 width=706) Sort Key: post.modified -> Nested Loop (cost=978.96..1329.32 rows=22 width=706) -> Index Scan using forum_name on forum (cost=0.00..242.71 rows=1 width=271) Filter: (((contrib IS NULL) OR (contrib = ' '::text) OR (contrib ~~ '%b%'::text)) AND ((permission & 127) = permission)) -> Bitmap Heap Scan on post (cost=978.96..1086.28 rows=27 width=435) Recheck Cond: ((to_tsvector('english'::text, post.message) @@ to_tsquery('violence'::text)) AND (post.forum = forum.name)) Filter: (post.invisible <> 1) -> BitmapAnd (cost=978.96..978.96 rows=27 width=0) -> Bitmap Index Scan on idx_message (cost=0.00..370.57 rows=1435 width=0) Index Cond: (to_tsvector('english'::text, post.message) @@ to_tsquery('violence'::text)) -> Bitmap Index Scan on post_forum (cost=0.00..607.78 rows=26575 width=0) Index Cond: (post.forum = forum.name) (14 rows) ticker=# The difference in these two queries is that the second qualifies the returned search to check two permission blocks - one related to the user's permission bit mask, and the second a mask of single-character "flags" (the user's classification must be in the list of permitted classifications) Ok. Notice that the top-line cost of the first query is HIGHER. The first query runs almost instantly - average execution latency is frequently in the few-hundred millisecond range. The second query can take upward of 30 seconds (!) to run. Neither hits the disk, the machine in question has scads of free RAM available, and while busy is not particularly constrained. Other simultaneous users on the database are getting queries back immediately (no unreasonable delays). If I remove parts of the permission tests it does not matter. If ANY of those tests qualifies the returned values the performance goes in the toilet. If I re-order when the permission tests appear (e.g. at the end of the search command) it makes no difference in the response time either (it does, however, change the EXPLAIN output somewhat, and thereby appears to change the query plan. What's going on here? I can usually figure out what's causing bad performance and fix it with the judicious addition of an index or other similar thing - this one has me completely mystified. -- Karl --------------060708040808070501050806 Content-Type: text/x-vcard; charset=utf-8; name="karl.vcf" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="karl.vcf" begin:vcard fn:Karl Denninger n:Denninger;Karl org:Cuda Systems LLC adr;dom:;;314 Olde Post Road;Niceville;FL;32578 email;internet:karl@denninger.net tel;work:850-376-9364 tel;fax:850-897-9364 x-mozilla-html:TRUE url:http://market-ticker.org version:2.1 end:vcard --------------060708040808070501050806--