Skip to Main Content
  • Questions
  • Parallel DML Update without any parallel hint or parallel degree

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Prasun.

Asked: October 16, 2017 - 1:50 am UTC

Last updated: October 16, 2017 - 3:55 pm UTC

Version: 11.2.0.4.0

Viewed 10K+ times! This question is

You Asked

Hello All,

In our production environment, one DML update is running in parallel and which is sporadic in nature.
Please note the session is enabled for parallel dml.

Find below one pseudo code of that update statement.

---------------
ALTER SESSION ENABLE PARALLEL DML;

UPDATE TABLE_1 A
SET 
  A.COLUMN_1 =
       (SELECT COUNT(*)
        FROM TABLE_2 B
        WHERE B.KEY_COL = A.KEY_COL)
WHERE 
 A.KEY_COL IN
  (SELECT DISTINCT KEY_COL FROM TABLE_2)

------------

The parallel degree for TABLE_1 (target table and partitioned) is set as 1
The parallel degree for TABLE_2 (used in predicate) is set as DEFAULT (16)
Database Version - 11.2.0.4.0

-----------

parallel_adaptive_multi_user = FALSE
parallel_degree_limit = 16
parallel_degree_policy = auto
parallel_force_local FALSE
----------

My understanding was, if we don't add parallel hint (UPDATE /*+ parallel */) and DEGREE is set as 1 for target table , then DML Update will not execute in parallel although the session is enabled for parallel DML.

Can you please let me know if my understanding is correct ?

Appreciate your help.

and Chris said...

Not quite...

There are two parts to your SQL:

- The update
- The query to access the other table

The optimizer can parallelize both or just the query and not the update.

If you have parallel_degree_policy set to manual or limited, then the optimizer will choose parallelism based on the table settings or hint.

Here we have parallel 1 for the target table and 2 for the source. So the query is parallized, but not the update:

alter session enable parallel dml;
alter session enable parallel query;
alter session set statistics_level = all;
set serveroutput off
create table t1 (x) as 
  select rownum x from dual
  connect by level <= 10000;
create table t2 (x) as 
  select rownum x from dual
  connect by level <= 10000;
alter table t2 parallel ;

exec dbms_stats.gather_table_stats(user, 'T1');
exec dbms_stats.gather_table_stats(user, 'T2');

alter session set parallel_degree_policy = manual;

update t1
set   x = (
  select count(*) from t2
);

select * from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +PARALLEL +NOTE'));

PLAN_TABLE_OUTPUT                                                           
EXPLAINED SQL STATEMENT:                                                    
------------------------                                                    
update t1 set   x = (   select count(*) from t2 )                           
                                                                            
Plan hash value: 3079932949                                                 
                                                                            
-------------------------------------------------------------------------   
| Id  | Operation               | Name     |    TQ  |IN-OUT| PQ Distrib |   
-------------------------------------------------------------------------   
|   0 | UPDATE STATEMENT        |          |        |      |            |   
|   1 |  UPDATE                 | T1       |        |      |            |   
|   2 |   TABLE ACCESS FULL     | T1       |        |      |            |   
|   3 |   SORT AGGREGATE        |          |        |      |            |   
|   4 |    PX COORDINATOR       |          |        |      |            |   
|   5 |     PX SEND QC (RANDOM) | :TQ10000 |  Q1,00 | P->S | QC (RAND)  |   
|   6 |      SORT AGGREGATE     |          |  Q1,00 | PCWP |            |   
|   7 |       PX BLOCK ITERATOR |          |  Q1,00 | PCWC |            |   
|   8 |        TABLE ACCESS FULL| T2       |  Q1,00 | PCWP |            |   
-------------------------------------------------------------------------   
                                                                            
Note                                                                        
-----                                                                       
   - PDML disabled because object is not decorated with parallel clause     

commit;


But you also have parallel_degree_policy = auto. So the database will automatically determine the appropriate degree of parallelism. This overrides whatever you set as the parallel level for the table:

alter session set parallel_degree_policy = auto;
  
update t1
set   x = (
  select count(*) from t2
);

select * from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +PARALLEL +NOTE'));

PLAN_TABLE_OUTPUT                                                                       
EXPLAINED SQL STATEMENT:                                                                
------------------------                                                                
update t1 set   x = (   select count(*) from t2 )                                       
                                                                                        
Plan hash value: 2278366140                                                             
                                                                                        
------------------------------------                                                    
| Id  | Operation           | Name |                                                    
------------------------------------                                                    
|   0 | UPDATE STATEMENT    |      |                                                    
|   1 |  UPDATE             | T1   |                                                    
|   2 |   TABLE ACCESS FULL | T1   |                                                    
|   3 |   SORT AGGREGATE    |      |                                                    
|   4 |    TABLE ACCESS FULL| T2   |                                                    
------------------------------------                                                    
                                                                                        
Note                                                                                    
-----                                                                                   
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold   
   - PDML disabled because object is not decorated with parallel clause                 

commit;

alter table t1 parallel 2;
update t1
set   x = (
  select count(*) from t2
);

select * from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +PARALLEL +NOTE'));

PLAN_TABLE_OUTPUT                                                                       
EXPLAINED SQL STATEMENT:                                                                
------------------------                                                                
update t1 set   x = (   select count(*) from t2 )                                       
                                                                                        
Plan hash value: 2278366140                                                             
                                                                                        
------------------------------------                                                    
| Id  | Operation           | Name |                                                    
------------------------------------                                                    
|   0 | UPDATE STATEMENT    |      |                                                    
|   1 |  UPDATE             | T1   |                                                    
|   2 |   TABLE ACCESS FULL | T1   |                                                    
|   3 |   SORT AGGREGATE    |      |                                                    
|   4 |    TABLE ACCESS FULL| T2   |                                                    
------------------------------------                                                    
                                                                                        
Note                                                                                    
-----                                                                                   
   - automatic DOP: Computed Degree of Parallelism is 1 because of parallel threshold   
   - PDML disabled because object is not decorated with parallel clause                 

commit;


If your table grows large enough or you lower the threshold for parallelizing low enough (default 10s), then the database will choose the level of parallelism for you.

Let's lower the threshold to 1s and make the table look huge by setting the stats to 1 billion rows:

alter session set parallel_min_time_threshold = 1;
exec dbms_stats.set_table_stats( user, 'T1' , numrows => 1000000000, numblks => 1000000 );
update t1
set   x = (
  select count(*) from t2
);

select * from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +PARALLEL +NOTE'));

PLAN_TABLE_OUTPUT                                                                 
EXPLAINED SQL STATEMENT:                                                          
------------------------                                                          
update t1 set   x = (   select count(*) from t2 )                                 
                                                                                  
Plan hash value: 4037313505                                                       
                                                                                  
-----------------------------------------------------------------------           
| Id  | Operation             | Name     |    TQ  |IN-OUT| PQ Distrib |           
-----------------------------------------------------------------------           
|   0 | UPDATE STATEMENT      |          |        |      |            |           
|   1 |  PX COORDINATOR       |          |        |      |            |           
|   2 |   PX SEND QC (RANDOM) | :TQ10000 |  Q1,00 | P->S | QC (RAND)  |           
|   3 |    UPDATE             | T1       |  Q1,00 | PCWP |            |           
|   4 |     PX BLOCK ITERATOR |          |  Q1,00 | PCWC |            |           
|   5 |      TABLE ACCESS FULL| T1       |  Q1,00 | PCWP |            |           
|   6 |     SORT AGGREGATE    |          |        |      |            |           
|   7 |      TABLE ACCESS FULL| T2       |        |      |            |           
-----------------------------------------------------------------------           
                                                                                  
Note                                                                              
-----                                                                             
   - automatic DOP: Computed Degree of Parallelism is 4 because of degree limit   
 
commit;


In this case the optimizer chose a parallel degree of 4.

To use a particular level of parallelism, you need to use a hint:

update /*+ parallel (2) */t1
set   x = (
  select count(*) from t2
);

select * from table(dbms_xplan.display_cursor(null, null, 'BASIC LAST +PARALLEL +NOTE'));

PLAN_TABLE_OUTPUT                                                         
EXPLAINED SQL STATEMENT:                                                  
------------------------                                                  
update /*+ parallel (2) */t1 set   x = (   select count(*) from t2 )      
                                                                          
Plan hash value: 4037313505                                               
                                                                          
-----------------------------------------------------------------------   
| Id  | Operation             | Name     |    TQ  |IN-OUT| PQ Distrib |   
-----------------------------------------------------------------------   
|   0 | UPDATE STATEMENT      |          |        |      |            |   
|   1 |  PX COORDINATOR       |          |        |      |            |   
|   2 |   PX SEND QC (RANDOM) | :TQ10000 |  Q1,00 | P->S | QC (RAND)  |   
|   3 |    UPDATE             | T1       |  Q1,00 | PCWP |            |   
|   4 |     PX BLOCK ITERATOR |          |  Q1,00 | PCWC |            |   
|   5 |      TABLE ACCESS FULL| T1       |  Q1,00 | PCWP |            |   
|   6 |     SORT AGGREGATE    |          |        |      |            |   
|   7 |      TABLE ACCESS FULL| T2       |        |      |            |   
-----------------------------------------------------------------------   
                                                                          
Note                                                                      
-----                                                                     
   - Degree of Parallelism is 2 because of hint

commit;


Read more about auto degree of parallelism at:

https://blogs.oracle.com/datawarehousing/what-is-auto-dop
https://blogs.oracle.com/datawarehousing/configuring-and-controlling-auto-dop
https://blogs.oracle.com/datawarehousing/optimizer-processing-rates-for-auto-dop

Is this answer out of date? If it is, please let us know via a Comment

More to Explore

Performance

Get all the information about database performance in the Database Performance guide.