如露亦如电

一切有为法,如梦幻泡影,如露亦如电,应作如是观

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  370 随笔 :: 0 文章 :: 0 评论 :: 0 引用

 

作为18c的新特性,其实在oracle 12.2 引入了Scalable Sequences作为一个隐藏特性,为了改善在高并发系统中,
特别是使用seq作为index,大量插入记录导致index的争用,oracle自己实现了以前我们需要人工去自定义seq的方式(instance+sid+seq的类似算法方式),
该功能将在oracle 18c中正式推出,我这里带领大家先体会下
SCALE
/NOSCALE When SCALE is specified, a numeric offset is affixed to the beginning of the sequence. This offset if of the form iii||sss||, where, iii denotes a three digit instance offset given by (instance_id % 100) + 100, sss denotes a three digits session offset given by (session_id % 1000), and || is the concatenation operator EXTEND/NOEXTEND When EXTEND is specified with the SCALE keyword, the generated sequence values are all of length (x+y),

where x is the length of the scalable offset (default 6), and y is the maximum number of digits in the sequence maxvalue/minvalue. Thus,

for an ascending sequence with maxvalue 100 and SCALABLE EXTEND specified, the generated sequence values are of the form iii||sss||001, iii||sss||002, …,iii||sss||100 The default setting for the SCALE clause is NOEXTEND. With the NOEXTEND setting,
the generated sequence values are at most as wide as the maximum number of digits in the sequence maxvalue/minvalue.
This setting is useful for integration with existing applications where sequences are used to populate fixed width columns.

On invocation of NEXTVAL on a sequence with SCALABLE NOEXTEND specified, a user error is thrown if the generated value requires more digits

of representation than the sequence’s maxvalue/minvalue.
SCALE的算法就是(instance_id
% 100)(_kqdsn_instance_digits) + 100||(session_id % 1000)(_kqdsn_cpu_digits)+seq(EXTEND/NOEXTEND确定是否固定宽度) Scalable Sequences语法 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} ] Scalable Sequences测试 [oracle@xifenfei ~]$ sqlplus / as sysdba SQL*Plus: Release 12.2.0.1.0 Production on Tue Jan 23 02:33:49 2018 Copyright (c) 1982, 2016, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production BANNER CON_ID -------------------------------------------------------------------------------- ---------- Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production 0 PL/SQL Release 12.2.0.1.0 - Production 0 CORE 12.2.0.1.0 Production 0 TNS for Linux: Version 12.2.0.1.0 - Production 0 NLSRTL Version 12.2.0.1.0 - Production 0 SQL> set line 150 SQL> col "Paramete" for a30 SQL> col "Session Value" for a20 SQL> col "Instance Value" for a20 SQL> col "Is Default?" for a20 SQL> SELECT a.ksppinm "Parameter", b.ksppstvl "Session Value", c.ksppstvl "Instance Value",c.ksppstdf "Default?" 2 FROM x$ksppi a, x$ksppcv b, x$ksppsv c WHERE a.indx = b.indx AND a.indx = c.indx AND lower(a.ksppinm) 3 in ('_kqdsn_instance_digits', '_kqdsn_cpu_digits'); Parameter Session Value Instance Value Default? -------------------------------------------------------- -------------------- -------------------- --------- _kqdsn_instance_digits 2 2 TRUE _kqdsn_cpu_digits 3 3 TRUE SQL> select instance_number from v$instance; INSTANCE_NUMBER --------------- 1 SQL> select sys_context('userenv','sid') from dual; SYS_CONTEXT('USERENV','SID') ---------------------------------------------------------------------------- 275 SQL> create sequence seq_xff start with 1 increment by 1 minvalue 1 maxvalue 100 scale extend; Sequence created. SQL> select seq_xff.nextval from dual; NEXTVAL ---------- 101275001 验证效果 --另外一个会话 [oracle@xifenfei ~]$ sqlplus / as sysdba SQL*Plus: Release 12.2.0.1.0 Production on Tue Jan 23 02:45:14 2018 Copyright (c) 1982, 2016, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production SQL> select sys_context('userenv','sid') from dual; SYS_CONTEXT('USERENV','SID') --------------------------------------------------------- 4 SQL> select instance_number from v$instance; INSTANCE_NUMBER --------------- 1 SQL> select seq_xff.nextval from dual; NEXTVAL ---------- 101004002 这里可以看出来seq的值是固定长度的.而且随着sid或者inst_id 不同而不同,从而实现减少大量数据集中在一个block而引起的各种争用 测试scale noextend SQL> create sequence seq_xifenfei start with 1 increment by 1 minvalue 1 maxvalue 100 scale noextend; Sequence created. SQL> select seq_xifenfei.nextval from dual; select seq_xifenfei.nextval from dual * ERROR at line 1: ORA-64603: NEXTVAL cannot be instantiated for seq_xifenfei. Widen the sequence by 4 digits or alter sequence with SCALE EXTEND. SQL> drop sequence seq_xifenfei; Sequence dropped. SQL> create sequence seq_xifenfei start with 1 increment by 1 minvalue 1 maxvalue 1000000 scale noextend; Sequence created. SQL> select seq_xifenfei.nextval from dual; NEXTVAL ---------- 1010041 这里可以看出来scale noextend的长度是随着seq值的改变而改变,而且max值不能小于seq本身长度.

==============================================================================================================

 

资料2:

 

说明
在18c之前的版本中对于序列的使用,存在着对同一个序列争用的情况,特别是对于RAC这种高并发的环境中争用序列情况更是容易发生。
针对这种情况,Oracle退出了可伸缩序列,大大减少了序列和所在索引的争用,并提供了更好的数据负载可伸缩性。而对于单实例也同样有用。

创建可伸缩序列
语法
通过加SCALE关键字就可以创建可伸缩序列
CREATE | ALTER SEQUENCE sequence_name
...
SCALE [EXTEND | NOEXTEND] | NOSCALE
...

 

可伸缩序列=6位可伸缩序列偏移量数+正常的序列
6位可伸缩序列偏移量数=[(instance id % 100) + 100]+[会话ID % 1000]

EXTEND
表示序列总长度=[X个数字+Y个数字],X默认值是6位数,Y是MAXVALUE指定的位数。

NOEXTEND
表示序列总长度不能超过MAXVALUE定义的长度,由于前面默认是6位数+正常的序列号,所以长度最少是7位数。

实验


创建EXTEND类型的可伸缩序列
查看会话ID和实例号
SQL> select sys_context('userenv','sid') from dual;
SYS_CONTEXT('USERENV','SID')
--------------------------------------------------------------------------------
69

SQL> select instance_number from v$instance;
INSTANCE_NUMBER
---------------
1

 

创建序列
SQL> create sequence lei_seq start with 1 increment by 1 minvalue 1 maxvalue 100 scale extend;

Sequence created.

 

查看序列值
SQL> select lei_seq.nextval from dual;
NEXTVAL
-----------------------
101069001 = 101+069+001

 

再开一个会话查看序列值
会话ID不同,生成的序列肯定不会相同,但是最后3位是依次增长的。
SQL> select sys_context('userenv','sid') from dual;

SYS_CONTEXT('USERENV','SID')
--------------------------------------------------------------------------------
101

SQL> select lei_seq.nextval from dual;
NEXTVAL
----------
101101002

==============================================================================================================
==============================================================================================================
==============================================================================================================


创建NOEXTEND类型的可伸缩序列
SQL> create sequence lei_seq2 start with 1 increment by 1 minvalue 1 maxvalue 100 scale noextend;

Sequence created.

 

SQL> select lei_seq2.nextval from dual;

select lei_seq2.nextval from dual

*

ERROR at line 1:

ORA-64603: NEXTVAL cannot be instantiated for LEI_SEQ2. Widen the sequence by 4

digits or alter sequence with SCALE EXTEND.

 

可以看到报错了序列无法实例化,提示要么去掉maxvalue参数,要么使用extend。

错误原因很简单,因为noextend的可伸缩序列最少要7位数。

修改可以修改maxvalue为1000000即可,也就是6位数+1,一直增长到9就无法增长了,因为增长到10就会超过7位数。证明如下:

SQL> alter sequence lei_seq2 maxvalue 1000000;
Sequence altered.
1
2
重复执行几次

SQL> select lei_seq2.nextval from dual;
NEXTVAL
----------
1011011

SQL> /
NEXTVAL
----------
1011018

SQL> /
NEXTVAL
----------
1011019

SQL> /
select lei_seq2.nextval from dual
*
ERROR at line 1: --可以看到超过9就报错了,因为序列总长度超过了7位。
ORA-64603: NEXTVAL cannot be instantiated for LEI_SEQ2. Widen the sequence by 1
digits or alter sequence with SCALE EXTEND.

 

总结
对于可伸缩序列来说EXTEND和NOEXTEND没有本质区别,MAXVALUE代表的含义有所不同。

对于EXTEND来说MAXVALUE代表的后面正常序列的长度,而不是可伸缩序列的总长度。
对于NOEXTED来说MAXVALUE代表的是可伸缩序列的总长度。
注:Oracle建议对于可伸缩序列不要使用排序,因为它本身就是无序的。

 

posted on 2020-07-13 15:08  ~如露亦如电~  阅读(27)  评论(0编辑  收藏