X-Original-To: pgsql-performance-postgresql.org@localhost.postgresql.org Received: from localhost (av.hub.org [200.46.204.144]) by svr1.postgresql.org (Postfix) with ESMTP id 601C3D84AC for ; Mon, 24 Oct 2005 00:58:26 -0300 (ADT) Received: from svr1.postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 92854-06 for ; Mon, 24 Oct 2005 03:58:24 +0000 (GMT) Received: from deliverator7.gatech.edu (deliverator7.gatech.edu [130.207.165.169]) by svr1.postgresql.org (Postfix) with ESMTP id 2E5B3DAC28 for ; Mon, 24 Oct 2005 00:58:24 -0300 (ADT) Received: from hormel1.gatech.edu (hormel1.prism.gatech.edu [130.207.171.11]) (using TLSv1 with cipher EDH-RSA-DES-CBC3-SHA (168/168 bits)) (Client CN "hormel1.prism.gatech.edu", Issuer "Tech Support CA" (verified OK)) by deliverator7.gatech.edu (Postfix) with ESMTP id A5F3920DA for ; Sun, 23 Oct 2005 23:58:23 -0400 (EDT) (envelope-from edmonds42@bellsouth.net) Received: from ([130.207.171.121]) by hormel1.gatech.edu with ESMTP with TLS id KP-BRAPX.30421660; Sun, 23 Oct 2005 23:58:11 -0400 Received: from deliverator1.gatech.edu (localhost [127.0.0.1]) by localhost (Postfix) with ESMTP id 584021FAB84 for ; Sun, 23 Oct 2005 23:58:11 -0400 (EDT) (envelope-from edmonds42@bellsouth.net) Received: from mailprx3.gatech.edu (mailprx3.prism.gatech.edu [130.207.171.17]) (using TLSv1 with cipher EDH-RSA-DES-CBC3-SHA (168/168 bits)) (Client CN "smtp.mail.gatech.edu", Issuer "RSA Data Security? Inc." (verified OK)) by deliverator1.gatech.edu (Postfix) with ESMTP id 42CCE1FAB83 for ; Sun, 23 Oct 2005 23:58:11 -0400 (EDT) (envelope-from edmonds42@bellsouth.net) Received: from localhost (r54h98.res.gatech.edu [128.61.54.98]) (using TLSv1 with cipher DES-CBC3-SHA (168/168 bits)) (No client certificate requested) (sasl: method=PLAIN, username=gtg698r@mailprx3.gatech.edu, sender=n/a) by mailprx3.gatech.edu (Postfix) with ESMTP id 0793120B8 for ; Sun, 23 Oct 2005 23:58:11 -0400 (EDT) (envelope-from edmonds42@bellsouth.net) Date: Sun, 23 Oct 2005 23:58:09 -0400 From: Robert Edmonds To: pgsql-performance@postgresql.org Subject: performance of implicit join vs. explicit conditions on inet queries? Message-ID: <20051024035809.GA18261@edmonds.ath.cx> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-GT-Spam-Details: ESP<-39>=RBL:<-50> RDNS:<0> SHA:<11> UHA:<0> SLS:<0> BAYES:<0> SenderID:<0> GT_Custom:<0> NigeriaScam Dictionary (TRU8):<0> ReDictionary:<0> HTML Dictionary (TRU8):<0> Adult Dictionary (TRU8):<0> Spam Dictionary (TRU8):<0> Embed HTML Dictionary (TRU8):<0> Obscenities Dictionary (TRU8):<0> URL Dictionary (TRU8):<0> CAN-SPAM Compliance Dictionary (TRU8):<0> X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, hits=1.972 required=5 tests=[DNS_FROM_RFC_POST=1.376, FROM_ENDS_IN_NUMS=0.516, NORMAL_HTTP_TO_IP=0.08] X-Spam-Level: * X-Archive-Number: 200510/326 X-Sequence-Number: 15094 The preliminaries: - PostgreSQL 8.1 beta 3, Debian experimental - database has been VACUUMed FULL ANALYZE. - a pg_dump -Fc exists at http://199.77.129.48/inet_test.db - ia32 hardware with 2 GB physical memory and the following settings: shared_buffers = 40960 temp_buffers = 16384 work_mem = 131072 maintenance_work_mem = 262144 effective_cache_size = 65536 I've populated a table evenly with about 2 million rows of RFC 1918 addresses: Table "public.inet_addresses" Column | Type | Modifiers --------+------+----------- addr | inet | not null Indexes: "inet_addresses_pkey" PRIMARY KEY, btree (addr) The following query is very fast: EXPLAIN ANALYZE SELECT * FROM inet_addresses WHERE addr << inet('10.2.0.0/24') OR addr << inet('10.4.0.0/24') OR addr << inet('10.8.0.0/24'); Bitmap Heap Scan on inet_addresses (cost=6.51..324.48 rows=1792335 width=11) (actual time=0.350..1.104 rows=381 loops=1) Recheck Cond: ((addr << '10.2.0.0/24'::inet) OR (addr << '10.4.0.0/24'::inet) OR (addr << '10.8.0.0/24'::inet)) Filter: ((addr << '10.2.0.0/24'::inet) OR (addr << '10.4.0.0/24'::inet) OR (addr << '10.8.0.0/24'::inet)) -> BitmapOr (cost=6.51..6.51 rows=85 width=0) (actual time=0.336..0.336 rows=0 loops=1) -> Bitmap Index Scan on inet_addresses_pkey (cost=0.00..2.17 rows=28 width=0) (actual time=0.127..0.127 rows=127 loops=1) Index Cond: ((addr > '10.2.0.0/24'::inet) AND (addr <= '10.2.0.255'::inet)) -> Bitmap Index Scan on inet_addresses_pkey (cost=0.00..2.17 rows=28 width=0) (actual time=0.109..0.109 rows=127 loops=1) Index Cond: ((addr > '10.4.0.0/24'::inet) AND (addr <= '10.4.0.255'::inet)) -> Bitmap Index Scan on inet_addresses_pkey (cost=0.00..2.17 rows=28 width=0) (actual time=0.096..0.096 rows=127 loops=1) Index Cond: ((addr > '10.8.0.0/24'::inet) AND (addr <= '10.8.0.255'::inet)) Total runtime: 1.613 ms Instead of specifying explicit address ranges in the query, I'd like to store the ranges in a table: inet_test_db=# \d inet_ranges Table "public.inet_ranges" Column | Type | Modifiers ----------+---------+----------- range | inet | not null range_id | integer | Indexes: "inet_ranges_pkey" PRIMARY KEY, btree (range) "inet_ranges_range_id_idx" btree (range_id) inet_test_db=# SELECT * FROM inet_ranges; range | range_id --------------+---------- 10.2.0.0/24 | 1 10.4.0.0/24 | 1 10.8.0.0/24 | 1 10.16.0.0/24 | 2 10.32.0.0/24 | 2 10.64.0.0/24 | 2 (6 rows) This query is far slower, even though it generates the same result: EXPLAIN ANALYZE SELECT * FROM inet_addresses as ia, inet_ranges as ir WHERE ia.addr << ir.range AND ir.range_id=1; Nested Loop (cost=0.00..171485.93 rows=3072574 width=26) (actual time=1465.803..16922.979 rows=381 loops=1) Join Filter: ("inner".addr << "outer".range) -> Seq Scan on inet_ranges ir (cost=0.00..1.07 rows=3 width=15) (actual time=0.008..0.021 rows=3 loops=1) Filter: (range_id = 1) -> Seq Scan on inet_addresses ia (cost=0.00..31556.83 rows=2048383 width=11) (actual time=0.003..2919.405 rows=2048383 loops=3) Total runtime: 16923.457 ms Even when disabling sequential scans, the query planner is unable to make use of the inet_addresses_pkey index: Nested Loop (cost=100033605.21..100171874.11 rows=3072574 width=26) (actual time=2796.928..23453.585 rows=381 loops=1) Join Filter: ("inner".addr << "outer".range) -> Index Scan using inet_ranges_range_id_idx on inet_ranges ir (cost=0.00..3.04 rows=3 width=15) (actual time=0.069..0.095 rows=3 loops=1) Index Cond: (range_id = 1) -> Materialize (cost=100033605.21..100054089.04 rows=2048383 width=11) (actual time=0.016..5133.349 rows=2048383 loops=3) -> Seq Scan on inet_addresses ia (cost=100000000.00..100031556.83 rows=2048383 width=11) (actual time=0.005..2938.012 rows=2048383 loops=1) Total runtime: 23521.418 ms Is it possible to attain the speed of the first query and the flexibility of the second? Or will I have to resort to generating queries of the first form with the range table in the application layer? -- Robert Edmonds edmonds42@bellsouth.net