The Oracle Sponge

Oracle Data Warehouse Design and Architecture

Archive for April 1st, 2008

Discarding the Output of a Select Statement

Posted by David Aldridge on 2008-04-01

I’ve wondered before about a convenient way to tackle a particular problem — you want to run a select for a big bunch of rows, maybe for measuring wait events for a tricky query, but you want to discard the output so you don’t incur the network traffic and waits to the client. You could use autotrace in sql*plus, but how about something more generic? I’ve seen queries pushed to an in-line view with a 1=0 predicate and a no_push_pred (?) hint, and even seen people erroneously replace the projected rows with a simple count(*) — the latter often affecting the execution plan as an unintended side-effect. But it’s not like you can just pipe it to /dev/null, and you want something pretty tool independent.

Then I thought of this:

insert all   

when 1=0 then into s_order   

select * from s_order where ...   

/

It simply discards all the rows projected from the select statement, and the optimizer doesn’t push the 1=0 condition into the select statement as a plan-modifying predicate either (10.2).

explain plan for
insert into s_order
select * from s_order
/
select * from table(dbms_xplan.display)
/
-----------------------------------------------------------------------------        
| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |        
-----------------------------------------------------------------------------        
|   0 | INSERT STATEMENT  |         |    11M|  5052M|   446K  (1)| 02:13:56 |        
|   1 |  TABLE ACCESS FULL| S_ORDER |    11M|  5052M|   446K  (1)| 02:13:56 |        
----------------------------------------------------------------------------- 

explain plan for
insert all
when 1=0 then into s_order
select * from s_order
/
select * from table(dbms_xplan.display)
/
-------------------------------------------------------------------------------      
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |      
-------------------------------------------------------------------------------      
|   0 | INSERT STATEMENT    |         |    11M|  5052M|   446K  (1)| 02:13:56 |      
|   1 |  MULTI-TABLE INSERT |         |       |       |            |          |      
|   2 |   INTO              | S_ORDER |       |       |            |          |      
|   3 |    TABLE ACCESS FULL| S_ORDER |    11M|  5052M|   446K  (1)| 02:13:56 |      
------------------------------------------------------------------------------- 

explain plan for
insert all
when 1=0 then into s_order
select * from s_order where 1=0
/
select * from table(dbms_xplan.display)
/
--------------------------------------------------------------------------------     
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |     
--------------------------------------------------------------------------------     
|   0 | INSERT STATEMENT     |         |     1 |   445 |     0   (0)|          |     
|   1 |  MULTI-TABLE INSERT  |         |       |       |            |          |     
|   2 |   INTO               | S_ORDER |       |       |            |          |     
|*  3 |    FILTER            |         |       |       |            |          |     
|   4 |     TABLE ACCESS FULL| S_ORDER |    11M|  5052M|   446K  (1)| 02:13:56 |     
-------------------------------------------------------------------------------- 

Predicate Information (identified by operation id):                                  
---------------------------------------------------
3 - filter(NULL IS NOT NULL) 

explain plan for
insert into s_order
select * from s_order where 1=0
/
select * from table(dbms_xplan.display)
/
------------------------------------------------------------------------------       
| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |       
------------------------------------------------------------------------------       
|   0 | INSERT STATEMENT   |         |     1 |   445 |     0   (0)|          |       
|*  1 |  FILTER            |         |       |       |            |          |       
|   2 |   TABLE ACCESS FULL| S_ORDER |    11M|  5052M|   446K  (1)| 02:13:56 |       
------------------------------------------------------------------------------ 

Predicate Information (identified by operation id):                                  
---------------------------------------------------
1 - filter(NULL IS NOT NULL)           

So if you have a use for a filter on an insert statement that does not affect the optimizer’s execution plan (maybe for some esoteric optimizer problem?) then you could also use it for that.

Maybe there are more elegant solutions: after all this does require that you first make available a table with the correct columns and datatypes (with a CTAS and 1=0 condition, possibly). I bet there’s some other good ways though … ?

Posted in Oracle | 9 Comments »