【Oracle】 Oracle Sequence 性能优化

发布时间:2023年12月25日

Sequence是很简单的,如果最大程度利用默认值的话,我们只需要定义sequence对象的名字即可。在序列Sequence对象的定义中,Cache是一个可选择的参数。默认的Sequence对象是有cache选项的,默认取值为20。这个默认值对于大多数情况下都是够用的。?除非那种每秒上万次的select。?所以具体情况要具体对待。?对于哪些大并发的系统,最好设置在100以上。像移动的BOSS系统,以1000为单位。

SEQUENCE?创建基本语法:

CREATE?SEQUENCE?[schema.]sequence
[INCREMENT?BY?integer]?
[START?WITH?integer]?
[MAXVALUE?integer?|?NOMAXVALUE]?
[MINVALUE?integer?|?NOMINVALUE]?
[CYCLE?|?NOCYCLE]?
[CACHE?integer?|?NOCACHE]?
[ORDER?|?NOORDER]?

eg:

CREATE?SEQUENCE?emp_seq
INCREMENT?BY?1--?每次加几个?
START?WITH?1?--?从1开始计数?
NOMAXVALUE?--?不设置最大值?
NOCYCLE?--?一直累加,不循环?
CACHE?N?/?NOCACHE?--其中n代表一个整数,默认值为20。

如果指定CACHE值,Oracle就可以预先在内存里面放置一些Sequence,这样存取的快些。cache里面的取完后,Oracle自动再取一组到cache。使用cache或许会跳号,?比如数据库突然不正常down掉(shutdown?abort),cache中的Sequence就会丢失。举个例子:比如你的sequence中cache?100,那当你sequence取到90时突然断电,那么在你重启数据库后,sequence的值将从101开始。

如果指定NOCACHE值,Oracle就不会预先在内存里面存放Sequence,当然这也就可以避免数据库不正常down掉的sequence丢失。不过会产生一些问题:创建nocache?sequence在高并发访问时,容易导致row?cache?lock等待事件,主要原因是每次获取nextval时都需要修改rowcache中的字典信息。使用nocache?sequence,还会导致如下问题:
由于每次修改字典信息都需要commit,可能导致log?file?sync等待,nocache?sequence在RAC环境下,会对基于sequence生成的列创建的索引造成实例间大量索引块争用
基于以上问题,避免创建nocache?sequence。

再来看看sequence相关保护机制:
row?cache?lock:在调用sequence.nextval情况下需要修改数据字典时发生,对应row?cache?lock事件
SQ?lock:在内存缓存(并非rowcache)上获取sequence.nextval时发生,对应enq:SQ-contention事件
SV?lock:RAC环境下获取cache+order属性的sequence.nextval时发生,对应DFS?lock?handle事件

什么情况下使用cache什么时间上使用nocache?

个人感觉应该尽量使用cache,因为现在的数据库很多都是在高并发的情况下运行的,首先这样可以搞性能,并且也不会产生row?cache?lock等待事件。可能有些人会担心数据库不正常的down掉会产生序列号间断,但这也是很少的情况。当然如果你的业务要求是绝不能产生间断的序列号,那就要使用nochache了。

序列的并发访问?:
序列总是在数据库中生成唯一值,即使当多个用户并发地引用同一序列时也没有可察觉的等待或锁定。当多个用户使用?NEXTVAL?来增长序列时,每个用户生成一个其他用户不可见的唯一值。?
当多个用户并发地增加同一序列时,每个用户看到的值是有差异的。例如,一个用户可能从一个序列生成一组值,如?1、4、6?和?8,而另一个用户并发地从同一序列生成值?2、3、5?和?7。?

假如在创建sequence时,有意不选用cache选项,有2点需要注意:

1.?访问效率降低,没有cache功能的sequence取值将无法直接访问内存

2.?不论是nocache还是cache?,?每次访问nextval的过程都是不可逆的,在同一session中,在执行一系列dml和sequence的操作后,用户执行rollback,希望将操作回滚,但是sequence此时就显得异常顽固,用掉的nextval将无法被重现。当下一次试图读取nextval时,sequence的指针又移动到下一位了。

还有sequence不属于某个表,也不属于某个字段,sequence仅仅属于某个用户。

其实在创建了sequence后,每个表都可以使用这个sequence,但是这样会引起应用的很多麻烦,因此,建议每个表都使用一个sequence。
?

关于Sequence?order?参数的说明:

序参数:oracle默认是NOORDER,如果设置为ORDER;在单实例环境没有影响,在RAC环境此时,多实例实际缓存相同的序列,此时在多个实例并发取该序列的时候,会有短暂的资源竞争来在多实例之间进行同步。因次性能相比noorder要差,所以RAC环境非必须的情况下不要使用ORDER,尤其要避免NOCACHE?ORDER组合。?

order确保按照请求次序递增生成序列数字,在RAC环境中建议使用该选项。noorder不保证按请求次序生成,默认是noorder。


Cache参数对Sequence的使用带来什么好处?如果不设置,会有什么问题??

1、Sequence?Cache简析

简单的说,Cache?就是Oracle每次向Sequence进行请求时,分配出的独立数字数量。例如,当我们使用<seq_name>.nextval获取一个?独立值时,Oracle需要将sequence对象的数据字典信息更新。如果我们设置cache为10,那么第一次请求nextval的时候,就更新数据?字典信息增加10,取出的10个号放在Oracle服务器的缓存中。

在以后每次请求nextval的时候,Oracle就从服务器缓存中去获取序列值。而不需要更新数据字典信息。只有在分配到缓存的10个数字都已经分配完,或者因为缓存刷新操作剩余数字被清理的情况下,才会再次调用sequence分配机制,再次分出cache个数字。

在cache问题上,我们经常会疑惑为什么我们sequence生成的数字序列会“跳号”。这种跳号现象实际上就是因为cache的数字在缓存中因为各种原因被flush出,这样才导致生成的数字序列不连续。

注意:在有cache的情况下,sequence只能保证每次获取到的数字都是唯一、递增的,从来没有保证过数字的连续性。

如果我们不设置cache,也就是不启用序列数字缓存机制,有什么缺点呢?
1、过多的Redo?Log生成
a),对nocache的序列对象而言,每次操作都会有600左右的redo?log生成。?
b),对cache的sequence对象而言,redo?size生成的频率显然是低得多(到达cahce?size最大值时才会创建redo?log)。

设置cache之后,Oracle似乎不用为每次的nextval进行数据字典修改,生成redo?log记录。只有cache在内存中使用结束之后,才会进行获取。

在实际的生产环境中,我们对redo?size无必要的生成是要尽力避免的。首先,过多的redo?log生成,容易造成online?redo?log的写入量增加,切换频繁。第二,redo?size和nocache的使用,可能是伴随着频繁的commit动作,进而是频繁的log?buffer写入online?log?file的过程。同时归档量增加。同时,在进行恢复的时候,也要消耗更多的时间。

所以,设置cache可以有效减少redo?log的大小。

说明:?
如果我们处在一个高并发的情况下,系统频繁的多会话请求sequence取值。如果我们的sequence没有设置cache,那么每次都要更新数据字典,都要进行commit操作。多个会话还会出现该sequence记录的争用,出现等待事件row?lock?contention。?

在RAC环境下,cache和noorder选项的作用更大。在RAC中,多个实例争用情况会让sequence设计的不合理效果放大。所以,在没有特殊情况下,还是设置合理的cache值,减少系统潜在性能瓶颈。
?

文章来源:https://blog.csdn.net/wjianwei666/article/details/135182805
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。