Oracle 12.2.0.2/Oracle 18.1 新特性: Sequence SCALE EXTEND ?
从Oracle 12.2版本发布以后原只以为DBBP就已是关于和以前版本PSU相关最大的改变,但是并不是, 关注我WEIBO(@weejar)的朋友知道我在6月初发布过2条关于Oracle可能将改变ORACLE的版本和补丁称呼。其中一个改季度更新为RU (Release Update)和原PSU 更名 RUR (Release Update Revision),但不适用于12.1及以前版本,这点已见证,Oracle已经于201707发布了12.2的一个RU;另一个改变可能是ORACLE12C的是18.1(12.2.0.2),在MOS 742060.1中已证实。 叫什么不重要,这里我要分享的这个新特性是12.2 已经悄悄引入但undocument的,也可能会在下个RU公布,因为RU是可以引入小的特性的(RUR不会)。
在之前的版本或现在,对于表上的主键列或唯一约束的列的填充时会使用sequence, 利用sequnece的特性防止ID编号的重复, 但是在现实中如果高并发多会话insert表只是单纯的调 用sequnect nextval时,会发现主键列或唯一列上的索引争用非常严重,造成了数据库加载时的瓶颈。 数据库中TOP event可能是enq: tx- index contention, buffer busy wait,如果是在两个节点上的insert还有可能会显示”gc”类的 热块争用事件。原因很简单就是因为索引是一种按KEY顺序存放的物理结构,在insert时所有会话问是在频繁的更新索引最后一个块(或几个块),才产生的因sequence顺序值填充index产生的索引块热块。相关的statistics是索引右侧的分裂leaf node 90-10 splits.
常用的优化手段都是围绕打散索引值,如hash partition index , reverse index. 如果使用hash也只是把1个段上的争用分摊给hash 的数量,但不能完全避免, 但是也知道对于索引如范围扫描等将不可用。对于reverse 是可以避免该类争用,但是又增加了索引维护里的I/O 次数,增加了存储的IOPS。 当然如果有一种方法可以让每个session有自己的sequence区间,这样就可以解决 该问题, 当然如果前期有考虑到该问题, 在优化时就建议应用使用如instance number+ sid + sequence的组合手动拼接数值就可以了。Oracle的强大就是与庞大的用户群合作互赢,把用户的最佳实践和需求引入ORACLE, 这个特性因为没有某些原因在12.2中都没有公开,但是SQL语法已经可用,暂时称做Sequence SCALE EXTEND 。注意公开前不建议在用户应用中使用。
anbob@pdbanbob:anbob> @desc dba_sequences; Name Null? Type ------------------------------- -------- ---------------------------- 1 SEQUENCE_OWNER NOT NULL VARCHAR2(128) 2 SEQUENCE_NAME NOT NULL VARCHAR2(128) 3 MIN_VALUE NUMBER 4 MAX_VALUE NUMBER 5 INCREMENT_BY NOT NULL NUMBER 6 CYCLE_FLAG VARCHAR2(1) 7 ORDER_FLAG VARCHAR2(1) 8 CACHE_SIZE NOT NULL NUMBER 9 LAST_NUMBER NOT NULL NUMBER 10 SCALE_FLAG VARCHAR2(1) 11 EXTEND_FLAG VARCHAR2(1) 12 SESSION_FLAG VARCHAR2(1) 13 KEEP_VALUE VARCHAR2(1) anbob@pdbanbob:anbob> create sequence seq_scale maxvalue 100000 scale; Sequence created. anbob@pdbanbob:anbob> select seq_scale.nextval from dual; select seq_scale.nextval from dual * ERROR at line 1: ORA-64603: NEXTVAL cannot be instantiated for SEQ_SCALE. Widen the sequence by 1 digits or alter sequence with SCALE EXTEND. anbob@pdbanbob:anbob> alter sequence seq_scale SCALE EXTEND; Sequence altered. anbob@pdbanbob:anbob> set numw 30 anbob@pdbanbob:anbob> select seq_scale.nextval from dual; NEXTVAL ------------------------------ 101147000001 1 row selected. anbob@pdbanbob:anbob> / NEXTVAL ------------------------------ 101147000002 1 row selected. anbob@pdbanbob:anbob> / NEXTVAL ------------------------------ 101147000003 1 row selected. anbob@pdbanbob:anbob> col SEQUENCE_OWNER for a10 anbob@pdbanbob:anbob> col SEQUENCE_NAME for a15 anbob@pdbanbob:anbob> @seq seq_scale SEQUENCE_O SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER S E S K ---------- --------------- ---------- ---------- ------------ - - ---------- ----------- - - - - ANBOB SEQ_SCALE 1 100000 1 N N 20 21 Y Y N N 1 row selected.
Note:
注意到在12.2的dba_sequences里就增加了这个特性的标识列,在启用了该特性后sequnece为2大部分组成,第1部分为系统扩展区间区,第2部分和以前一样是sequece值,长度为sequence的最大长前,前补0。 对于第1部分的扩展区间因为文档未公开还不确认其数的资源来源,但可以猜。
anbob@pdbanbob:anbob> select INSTANCE_NUMBER from v$instance; INSTANCE_NUMBER --------------- 1 anbob@pdbanbob:anbob> select sid from v$mystat where rownum<2; SID ------------------------------ 147 1 row selected. sys@pdbanbob:anbob> @pd sequence Show all parameters and session values from x$ksppi/x$ksppcv... NUM N_HEX NAME VALUE DESCRIPTION ---------- ----- --------------------------- ------------ ------------------------------------------------------ 2608 A30 _pdb_use_sequence_cache TRUE Use sequence cache in PDB mode 2919 B67 _kqdsn_instance_digits 2 number of instance digits in scalable sequence 2920 B68 _kqdsn_cpu_digits 3 number of cpu digits in scalable sequence
Note:
第1部分是1位是1,目前不知道其意义
第2部分是2位的实例号,如实例1是01,实例2是02
第3部分是3位的session id,如果SID为4位以上时可以测是否是后3位还是前3位?
第4部分是sequnece最大数位前用0补齐。
并且控制第2和3部分长度的参数应该是“_kqdsn_instance_digits”和“_kqdsn_cpu_digits”。
以上只是猜测。
如果启用了SCALE而未启用EXTEND,NO EXTEND区别是会把第一部分系统扩展区的长度算在最大长度内。
anbob@pdbanbob:anbob> create sequence seq_scale_noext maxvalue 1000000 scale; Sequence created. anbob@pdbanbob:anbob> select seq_scale_noext.nextval from dual; NEXTVAL ---------- 1011471 1 row selected. anbob@pdbanbob:anbob> select seq_scale_noext.nextval from dual; NEXTVAL ---------- 1011472 ... ... anbob@pdbanbob:anbob> select seq_scale_noext.nextval from dual; NEXTVAL ---------- 1011479 anbob@pdbanbob:anbob> select seq_scale_noext.nextval from dual; select seq_scale_noext.nextval from dual * ERROR at line 1: ORA-64603: NEXTVAL cannot be instantiated for SEQ_SCALE_NOEXT. Widen the sequence by 1 digits or alter sequence with SCALE EXTEND. anbob@pdbanbob:anbob> create sequence seq_scale_noext1 maxvalue 10000000 scale; Sequence created. anbob@pdbanbob:anbob> select seq_scale_noext1.nextval from dual; NEXTVAL ---------- 10114701 1 row selected.
Summary:
scale extend sequence这个功能非常的适用,可以有效的避免使用sequnece大并发insert时并生的索引块上的争用,包含了实例号和sid的组合及sequence的组合,只是出于某些原因并未把方法和使用公开到12.2的document中,相信在后续的版本中会公开,在公开前不建议使用在应用中。可以手动实现如
drop sequence seq_scale_nosca ; create sequence seq_scale_nosca maxvalue 10000000; SQL> select to_number(sys_context('userenv','INSTANCE')||userenv('SID')||lpad(seq_scale_nosca.nextval,7,0)) from dual; TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')||USERENV('SID')||LPAD(SEQ_SCALE_NOSCA.NEXTVAL,7,0)) ----------------------------------------------------------------------------------------------- 1330000001 SQL> r TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')||USERENV('SID')||LPAD(SEQ_SCALE_NOSCA.NEXTVAL,7,0)) ----------------------------------------------------------------------------------------------- 1330000002 SQL> r TO_NUMBER(SYS_CONTEXT('USERENV','INSTANCE')||USERENV('SID')||LPAD(SEQ_SCALE_NOSCA.NEXTVAL,7,0)) ----------------------------------------------------------------------------------------------- 1330000003
对不起,这篇文章暂时关闭评论。