版权声明:本文为Buddy Yuan原创文章,转载请注明出处。原文地址:Oracle Database 18c新特性-Scalable sequences
在我们日常维护的数据库中,在大规模插入的数据库应用中,经常会遇到”enq:TX-index contention”这类型的等待事件。并且这个问题发生在通过序列生成的递增键值上的尤其常见。索引叶子节点争用发生在基于用户生成的键(通过序列生成)插入行时,在这种插入的情况下,最近的条目将位于B树索引的最右边的叶子块中。这也意味着所有新行都将存储在索引的最右边的叶子块中,随着越来越多的会话向表中插入行,最右边的叶子块将塞满。Oracle将最右边的叶子块分为两个叶子块,其中一个块包含除一行之外的所有行,而另一个新块仅包含一行。这种类型的增长称为”Right Handed Growth”索引。随着越来越多的并发会话插入到索引的最右边的叶块中,该索引块成为热块,并且该叶块上的并发导致性能问题。在Oracle RAC数据库中,此问题被放大并成为更大的瓶颈。如果序列缓存很小(在特定于实例默认为20),则最右边的叶块不仅在一个实例中而且在集群的所有实例中都成为热块,并且该热块需要通过gc来回传输。
在Oracle Database 18c引入了一种称为可伸缩序列的新型序列。在那些具有高并发性的数据插入的情况下,通过生成无序主键或唯一键值的新可伸缩序列,可以帮助大大减少由右手索引引起的序列和索引块争用,这种和之前配置巨大的CACHE序列缓存解决方案相比较,吞吐量,数据负载可伸缩性和性能更好。
使用语法 CREATE | ALTER SEQUENCE [ schema. ]sequence [ { INCREMENT BY | START WITH } integer | { MAXVALUE integer | NOMAXVALUE } | { MINVALUE integer | NOMINVALUE } | { CYCLE | NOCYCLE } | { CACHE integer | NOCACHE } | { ORDER | NOORDER } | { SCALE {EXTEND | NOEXTEND} | NOSCALE} ]
默认我们创建一个索引,scale和extend都是关闭的
SQL> create sequence test_seq; Sequence created. SQL> create sequence test_seq scale; Sequence created. SQL> select sequence_name, scale_flag, extend_flag from user_sequences; SEQUENCE_NAME S E -------------------------------------------------------------------------------------------------------------------------------- - - TEST_SEQ Y N
现在使用scale子句创建序列。当指定scale子句时,在序列的数字前添加一个6位可伸缩序列偏移量数。6位可伸缩序列偏移量数的公式如下:[(instance_id % 100) + 100] || [session_id % 1000]生成的。
SQL> select sequence_name,max_value,scale_flag, extend_flag from user_sequences; SEQUENCE_NAME MAX_VALUE S E ---------------------------------------- ------------------------------------- - - TEST_SEQ 9999999999999999999999999999 Y N SQL> select test_seq.nextval from dual; NEXTVAL ---------------------------------- 1010310000000000000000000001 SQL> select test_seq.nextval from dual; NEXTVAL ---------------------------------- 1010310000000000000000000002
我们在看一下我们会话的inst_id和sid,可以看到前面6位数字的偏移量101031就是通过这两个计算出来的。
SQL> SELECT sys_context('USERENV', 'INSTANCE') inst_id, sys_context('USERENV', 'SID') sid FROM dual; INST_ID SID ---------------------------------------- ------------------------------ 1 31
当使用SCALE关键字在指定EXTEND时,生成的序列值全为长度(x + y),其中x为可伸缩偏移量的长度(默认为6),y为序列maxvalue指定的位数。noextend表示序列总长度不超过maxvalue定义的长度,由于前面默认是6位数+正常序列号,所以长度至少是7位。SCALE子句的默认设置为NOEXTEND。
SQL> SELECT sys_context('USERENV', 'INSTANCE') inst_id, sys_context('USERENV', 'SID') sid FROM dual; INST_ID SID ------------------------------ ------------------------------ 1 275 SQL> create sequence seq_extend start with 1 increment by 1 minvalue 1 maxvalue 100 scale extend; Sequence created. SQL> select seq_extend.nextval from dual; NEXTVAL ---------- 101275001 SQL> create sequence seq_noextend start with 1 increment by 1 minvalue 1 maxvalue 100 scale noextend; Sequence created. SQL> select seq_noextend.nextval from dual; select seq_noextend.nextval from dual * ERROR at line 1: ORA-64603: NEXTVAL cannot be instantiated for SEQ_NOEXTEND. Widen the sequence by 4 digits or alter sequence with SCALE EXTEND.
可以看到,我们使用NOEXTEND在当你的maxvalue小于7位的时候,就会报ORA-64603错误。
最后需要注意一点,Oracle建议不要为Scalable sequences指定顺序,因为Scalable sequences序列号是全局无序的。
参考链接:https://docs.oracle.com/en/database/oracle/oracle-database/18/admin/managing-views-sequences-and-synonyms.html#GUID-76663C84-D792-46A3-A25A-03C49DED71AD
Post a Comment