An
interesting question came up this morning with a fellow college about the
performance concern on using One Oracle sequence to generate primary key values
across many tables.
There is
only one sequence cache/latch per instance. So regardless if you have one or
thousand sequences this won’t change. The hot spot would be sys.seq$ - since
every now and then when we exhaust the value from cache, we update the value in
the dictionary (recursive sql) and that could produce contention in multi user
scenario.
I ran this
benchmark and the setup:
create sequence
seq1;
create sequence
seq2;
create sequence
seq3;
create sequence
seq4;
create sequence
seq5;
create sequence
seq6;
create sequence
seq7;
create sequence
seq8;
create sequence
seq9;
create sequence
seq10;
demo@ORA12C>
create or replace procedure p(x int default NULL)
  2  as
  3    
l_value int;
  4    
l_str long;
  5 
begin
  6    
if x is null then
  7            
l_str :=' select seq1.nextval from dual ';
  8     
else
  9            
l_str :=' select seq'||x||'.nextval from dual ';
 10    
end if;
 11
 12    
for i in 1..100000
 13    
loop
 14            
execute immediate l_str into l_value;
 15     end loop;
 16  end;
 17  /
Procedure
created.
Ran two invocations of the procedure,
first with ten concurrent sessions each with same sequence, then next with ten
concurrent sessions each with its own/different sequences.
demo@ORA12C>
variable x number
demo@ORA12C>
exec :x := dbms_workload_repository.create_snapshot;
PL/SQL
procedure successfully completed.
demo@ORA12C>
print x
         X
----------
      3760
demo@ORA12C>
declare
  2    
l_job int ;
  3 
begin
  4    
for i in 1..10
  5    
loop
  6            
dbms_job.submit( l_job, ' begin p; end; ');
  7    
end loop;
  8    
commit;
  9  end;
 10  /
PL/SQL
procedure successfully completed.
demo@ORA12C>
exec :x := dbms_workload_repository.create_snapshot;
PL/SQL
procedure successfully completed.
demo@ORA12C>
print x
         X
----------
      3761
demo@ORA12C>
declare
  2    
l_job int ;
  3 
begin
  4    
for i in 1..10
  5    
loop
  6            
dbms_job.submit( l_job, ' begin p('||i||'); end; ');
  7    
end loop;
  8    
commit;
  9  end;
 10  /
PL/SQL
procedure successfully completed.
demo@ORA12C>
exec :x := dbms_workload_repository.create_snapshot;
PL/SQL
procedure successfully completed.
demo@ORA12C>
print x
         X
----------
      3762
demo@ORA12C>
The AWR report for the first execution
(one sequence for all) report this:
Top 10
Foreground Events by Total Wait Time
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                          
Total Wait       Avg   % DB Wait
Event                                Waits Time (sec)      Wait  
time Class
------------------------------
----------- ---------- --------- ------ --------
enq: SQ - contention               175,240        144 
821.53us   43.7 Configur
DB CPU                                             51             15.5
library cache: mutex X               4,874         19   
3.89ms    5.8 Concurre
db file
sequential read                509        3.6   
7.08ms    1.1 User I/O
log file
sync                           12         .7  
59.11ms     .2 Commit
cursor: pin
S                          621         .6 
895.18us     .2 Concurre
latch free                           1,009         .2 
157.53us     .0 Other
control file
sequential read           198         .1 
582.89us     .0 System I
Disk file
operations I/O                19         .1   
4.48ms     .0 User I/O
kksfbc child
completion                  1          0  
49.52ms     .0 Other
The AWR report for the second execution
(different sequence for each) report this:
Top 10
Foreground Events by Total Wait Time
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                          
Total Wait       Avg   % DB Wait
Event                                Waits Time
(sec)      Wait   time Class
------------------------------
----------- ---------- --------- ------ --------
buffer busy
waits                    6,031       66.3  
11.00ms   31.8 Concurre
DB CPU                                          
50.9             24.4
latch free                           1,074        4.3  
 4.05ms    2.1 Other
latch: shared
pool                     548        2.4   
4.40ms    1.2 Concurre
db file
sequential read                215        1.1   
5.34ms     .5 User I/O
latch: cache
buffers chains             66         .3   
4.12ms     .1 Concurre
control file
sequential read           198         .1 
530.98us     .1 System I
db file
scattered read                  14         .1   
5.92ms     .0 User I/O
library cache
load lock                  8         .1   
8.12ms     .0 Concurre
log file sync                           12          0   
4.07ms     .0 Commit
So yes, there could be some contention
introduced by having a single sequence object for everything.
