Skip site navigation (1) Skip section navigation (2)

BUG #4934: regression in IN with joins in subselect

From: "Benjamin Reed" <ranger(at)opennms(dot)org>
To: pgsql-bugs(at)postgresql(dot)org
Subject: BUG #4934: regression in IN with joins in subselect
Date: 2009-07-22 18:47:52
Message-ID: 200907221847.n6MIlql9035866@wwwmaster.postgresql.org (view raw or flat)
Thread:
Lists: pgsql-bugs
The following bug has been logged online:

Bug reference:      4934
Logged by:          Benjamin Reed
Email address:      ranger(at)opennms(dot)org
PostgreSQL version: 8.4.0
Operating system:   Mac OS X 10.5
Description:        regression in IN with joins in subselect
Details: 

I've hit a regression vs. PostgreSQL 8.2 and 8.3 (and probably others)
related to subselects.  This query:

---(snip!)---
SELECT DISTINCT ipInterface.ipAddr FROM ipInterface
	JOIN node ON (ipInterface.nodeID = node.nodeID)
	JOIN ifServices ON (ipInterface.id = ifServices.ipInterfaceId)
	JOIN service ON (ifServices.serviceID = service.serviceID)
WHERE
	(
		node.nodeID IN (
			SELECT category_node.nodeID FROM category_node, categories
			WHERE categories.categoryID = category_node.categoryID
			AND categories.categoryName = 'IMP_mid'
		)
	) AND
	(
		node.nodeID IN (
			SELECT category_node.nodeID FROM category_node, categories
			WHERE categories.categoryID = category_node.categoryID
			AND categories.categoryName = 'DEV_AC'
		)
	) AND
	(
		node.nodeID IN (
			SELECT category_node.nodeID FROM category_node, categories
			WHERE categories.categoryID = category_node.categoryID
			AND categories.categoryName = 'OPS_Online'
		)
	) AND
	(node.nodeId = 1) AND
	(ipInterface.ipAddr = '192.168.1.1') AND
	(service.serviceName = 'ICMP')
LIMIT 1;
---(snip!)---

...passes in PostgreSQL 8.2 and 8.3 (which I have handy to test), but fail
in 8.4.0, as well as current origin/REL8_4_STABLE in git.  I reported it in
IRC, and the original hope was that it was related to bug #4906, but since
testing latest git, it appears that is not the case.

The query plan in 8.3 is this:

---(snip!)---
 Limit  (cost=4.27..76.68 rows=1 width=50)
   ->  Unique  (cost=4.27..76.68 rows=1 width=50)
         ->  Nested Loop IN Join  (cost=4.27..76.68 rows=1 width=50)
               ->  Nested Loop IN Join  (cost=4.27..60.12 rows=1 width=54)
                     ->  Nested Loop IN Join  (cost=4.27..43.56 rows=1
width=54)
                           ->  Nested Loop  (cost=4.27..26.99 rows=1
width=54)
                                 ->  Nested Loop  (cost=4.27..18.72 rows=1
width=54)
                                       ->  Nested Loop  (cost=4.27..17.90
rows=2 width=58)
                                             ->  Index Scan using
ipinterface_nodeid_ipaddr_ismanaged_idx on ipinterface  (cost=0.00..8.27
rows=1 width=58)
                                                   Index Cond: ((1 = nodeid)
AND ((ipaddr)::text = '192.168.1.1'::text))
                                             ->  Bitmap Heap Scan on
ifservices  (cost=4.27..9.60 rows=2 width=8)
                                                   Recheck Cond:
(ipinterface.id = ifservices.ipinterfaceid)
                                                   ->  Bitmap Index Scan on
ifservicves_ipinterfaceid_idx  (cost=0.00..4.27 rows=2 width=0)
                                                         Index Cond:
(ipinterface.id = ifservices.ipinterfaceid)
                                       ->  Index Scan using pk_serviceid on
service  (cost=0.00..0.40 rows=1 width=4)
                                             Index Cond:
(ifservices.serviceid = service.serviceid)
                                             Filter: ((servicename)::text =
'ICMP'::text)
                                 ->  Index Scan using node_id_type_idx on
node  (cost=0.00..8.27 rows=1 width=4)
                                       Index Cond: (nodeid = 1)
                           ->  Nested Loop  (cost=0.00..16.55 rows=1
width=4)
                                 ->  Index Scan using category_idx on
categories  (cost=0.00..8.27 rows=1 width=4)
                                       Index Cond: ((categoryname)::text =
'IMP_mid'::text)
                                 ->  Index Scan using catenode_unique_idx on
category_node  (cost=0.00..8.27 rows=1 width=8)
                                       Index Cond:
((public.categories.categoryid = public.category_node.categoryid) AND (1 =
public.category_node.nodeid))
                     ->  Nested Loop  (cost=0.00..16.55 rows=1 width=4)
                           ->  Index Scan using category_idx on categories 
(cost=0.00..8.27 rows=1 width=4)
                                 Index Cond: ((categoryname)::text =
'OPS_Online'::text)
                           ->  Index Scan using catenode_unique_idx on
category_node  (cost=0.00..8.27 rows=1 width=8)
                                 Index Cond: ((public.categories.categoryid
= public.category_node.categoryid) AND (1 = public.category_node.nodeid))
               ->  Nested Loop  (cost=0.00..16.55 rows=1 width=4)
                     ->  Index Scan using category_idx on categories 
(cost=0.00..8.27 rows=1 width=4)
                           Index Cond: ((categoryname)::text =
'DEV_AC'::text)
                     ->  Index Scan using catenode_unique_idx on
category_node  (cost=0.00..8.27 rows=1 width=8)
                           Index Cond: ((public.categories.categoryid =
public.category_node.categoryid) AND (1 = public.category_node.nodeid))
---(snip!)---

...and in the stable branch, this:

---(snip!)---
 Limit  (cost=16.56..72.51 rows=1 width=50)
   ->  Unique  (cost=16.56..72.51 rows=1 width=50)
         ->  Nested Loop Semi Join  (cost=16.56..72.51 rows=1 width=50)
               ->  Nested Loop Semi Join  (cost=16.56..55.94 rows=1
width=54)
                     ->  Nested Loop  (cost=16.56..39.38 rows=1 width=54)
                           ->  Nested Loop Semi Join  (cost=16.56..38.57
rows=2 width=58)
                                 ->  Index Scan using node_id_type_idx on
node  (cost=0.00..8.27 rows=1 width=4)
                                       Index Cond: (nodeid = 1)
                                 ->  Nested Loop  (cost=16.56..37.16 rows=2
width=62)
                                       ->  Nested Loop  (cost=16.56..24.85
rows=1 width=62)
                                             ->  Index Scan using
ipinterface_nodeid_ipaddr_ismanaged_idx on ipinterface  (cost=0.00..8.27
rows=1 width=58)
                                                   Index Cond: ((nodeid = 1)
AND ((ipaddr)::text = '192.168.1.1'::text))
                                             ->  HashAggregate 
(cost=16.56..16.57 rows=1 width=4)
                                                   ->  Nested Loop 
(cost=0.00..16.55 rows=1 width=4)
                                                         ->  Index Scan
using category_idx on categories  (cost=0.00..8.27 rows=1 width=4)
                                                               Index Cond:
((categoryname)::text = 'DEV_AC'::text)
                                                         ->  Index Scan
using catenode_unique_idx on category_node  (cost=0.00..8.27 rows=1
width=8)
                                                               Index Cond:
((public.category_node.categoryid = public.categories.categoryid) AND
(public.category_node.nodeid = 1))
                                       ->  Index Scan using
ifservicves_ipinterfaceid_idx on ifservices  (cost=0.00..12.29 rows=2
width=8)
                                             Index Cond:
(ifservices.ipinterfaceid = ipinterface.id)
                           ->  Index Scan using pk_serviceid on service 
(cost=0.00..0.39 rows=1 width=4)
                                 Index Cond: (service.serviceid =
ifservices.serviceid)
                                 Filter: ((service.servicename)::text =
'ICMP'::text)
                     ->  Nested Loop  (cost=0.00..16.55 rows=1 width=4)
                           ->  Index Scan using category_idx on categories 
(cost=0.00..8.27 rows=1 width=4)
                                 Index Cond: ((categoryname)::text =
'IMP_mid'::text)
                           ->  Index Scan using catenode_unique_idx on
category_node  (cost=0.00..8.27 rows=1 width=8)
                                 Index Cond:
((public.category_node.categoryid = public.categories.categoryid) AND
(public.category_node.nodeid = 1))
               ->  Nested Loop  (cost=0.00..16.55 rows=1 width=4)
                     ->  Index Scan using category_idx on categories 
(cost=0.00..8.27 rows=1 width=4)
                           Index Cond: ((categoryname)::text =
'OPS_Online'::text)
                     ->  Index Scan using catenode_unique_idx on
category_node  (cost=0.00..8.27 rows=1 width=8)
                           Index Cond: ((public.category_node.categoryid =
public.categories.categoryid) AND (public.category_node.nodeid = 1))
---(snip!)---

If I cut the select down to:

---(snip!)---
SELECT DISTINCT ipInterface.ipAddr FROM ipInterface
	JOIN node ON (ipInterface.nodeID = node.nodeID)
	JOIN ifServices ON (ipInterface.id = ifServices.ipInterfaceId)
	JOIN service ON (ifServices.serviceID = service.serviceID)
WHERE
	(node.nodeId = 1) AND
	(ipInterface.ipAddr = '192.168.1.1') AND
	(service.serviceName = 'ICMP')
LIMIT 1;
---(snip!)---

...it passes, but as soon as I add one of the node.nodeID IN() bits, it
fails.  Also, if I change it to hardcode one of the passing node IDs:

---(snip!)---
SELECT DISTINCT ipInterface.ipAddr FROM ipInterface
JOIN node ON (ipInterface.nodeID = node.nodeID)
JOIN ifServices ON (ipInterface.id = ifServices.ipInterfaceId)
JOIN service ON (ifServices.serviceID = service.serviceID)
WHERE
(
node.nodeID IN ( SELECT 1 )
) AND
(node.nodeId = 1) AND
(ipInterface.ipAddr = '192.168.1.1') AND
(service.serviceName = 'ICMP')
LIMIT 1;
---(snip!)---

...it passes, so it appears to be related specifically to the joined
subselect.

If there's anything else you need (database dumps, whatever) to help debug
this, let me know.

Thanks.

Responses

pgsql-bugs by date

Next:From: Magnus HaganderDate: 2009-07-22 18:51:30
Subject: Re: BUG #4932: Upgrade 8.2.13 -> 8.4.0 - Kerberos option missing
Previous:From: Aaron Marcuse-KubitzaDate: 2009-07-22 15:36:36
Subject: BUG #4933: ts_rewrite() causes segfault when query with more than one node becomes empty

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group