Re: Optimization question: Unrolling subquery into IN clause

From: Malcolm Dew-Jones <yf110_at_vtn1.victoria.tc.ca>
Date: 22 Oct 2009 10:46:03 -0700
Message-ID: <4ae09a5b$1_at_news.victoria.tc.ca>



Wolfram Roesler (wr_at_spam.la) wrote:
: Hello,

: I have a query that looks roughly like this:

: SELECT several_columns
: FROM tab1
: WHERE col1='Value'
: AND col2 IN
: (
: SELECT key
: FROM tab2
: WHERE tab2.col3='Something'
: );

: tab1 has about 1.7 million rows. There is an index on tab1.col1
: but it has low selectivity (the value queried here is matched by
: about 1/3 of all rows) so Oracle ignores the index and does a
: full table scan on tab1. It also does a full table scan on tab2
: for the subquery and then hash joins the two together. The FTS
: on tab1 takes about 4 seconds, the FTS on tab2 (since it's a
: smaller table) is negligable.

: However, only 20 rows of tab2 match the subquery, and only 300
: rows of tab1 match the entire query. When I unroll the subquery
: myself, i. e. do this first:

: SELECT key
: FROM tab2
: WHERE tab2.col3='Something';

: then save the returned keys and use these as an IN clause in
: my tab1 query WITHOUT a subquery, like this:

: SELECT several_columns
: FROM tab1
: WHERE col1='Value'
: AND col2 IN (Keys returned from tab2 query);

: both queries finish within a fraction of a second (since there
: is also on index on tab1.col2 which is now being used).

(snip)

Various people have spoken, but in quickly glancing through I did not see anything like the following. I think that this is a tom kyte trick (aren't they all). Obviously I haven't tested this to see if it helps you, but it has worked for me in other situations.

   google: materialize rownum
 might give you better examples. My (untested) first attempt would be

	SELECT several_columns
	FROM tab1
	WHERE col1='Value'
	AND col2 IN
	(
	      SELECT key
		from
		( SELECT rownum, key
	      	  FROM tab2
		  WHERE tab2.col3='Something'
		)
	);

You could also try using the rownum select in a WITH clause at the top. The rownum forces Oracle to build a small temporary materialized version of the inner select. Received on Thu Oct 22 2009 - 12:46:03 CDT

Original text of this message