Oracle自适应序列

通常序列的作用主要是为了生成唯一的整数,用来作为表的主键字段。因为序列的数值一直在不断地增长,通常每次增加一。每一个新增的条目都会被放在索引的最右边叶子块,会使得这个叶子块非常的热,从而产生争用,如果是在一起RAC集群当中,那么就会争用的更加厉害,会导致更多的集群等待事件。

为了改善以序列值作为键值的表的数据加载性能,从Oracle 18.1数据库开始,自适应序列 (Scalable Sequences) 被引入这个特性为序列提供了添加 instance 和 session 偏移量的选项,当跨 RAC节点加载数据或者单实例多个进程并发加载数据时,可以显著减少序列争用和索引块争用的可能性。

这个新特性的好处是,在以序列作为键值的表的数据加载时,它通过减少争用来进一步提升Oracle数据库加载数据的能力。在创建序列的时候,将 instance 和 session 的 id 添加到序列的值中,这样在生成序列值时产生的争用和 insert 键值时产生的索引块争用可以显著的减少。这表明Oracle数据库数据的数据加载能力可以进一步扩展,并且可以支撑更高速率的数据加载。

创建自适应序列的语法如下

1
2
3
4
5
6
7
8
9
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/NOSCALE

当 SCALE 被指定的时候,一个数字偏移量会附着在序列值的开头。

偏移量的表现形式为 iii||sss|| ,其中,
iii 表现为一个3个数字的instance偏移量,数值来源为: (instance_id % 100) + 100,
sss 表现为一个3个数字的instance偏移量,数值来源为:(session_id % 1000)
|| 是连接符

EXTEND/NOEXTEND

当 EXTEND 和 SCALE 关键字同时被指定时,产生的序列值的长度都是 (x+y),这里 x 是自适应偏移量 (默认是6),而 y 则是序列的 maxvalue/minvalue 关键字限定的最大值的数字位数。举例来说,如果一个升序的序列,maxvalue 被指定为100,并且指定了SCALABLE EXTEND关键字,那么产生的序列值的表现形式为 iii||sss||001,iii||sss||002 …… iii||sss||100

默认情况下 SCALE 是 NOEXTEND 的,当 NOEXTEND 被设置时,产生的序列值长度最大只能是序列 maxvalue/minvalue 关键字限定的最大值的数字位数。在某些应用中,序列被用来填充固定宽度的列,那么在整合这些应用时,这个设定很有用。在调用一个 SCALABLE NOEXTEND 的序列的 NEXTVAL 值时,如果产生的序列值需要的数字位数比 maxvalue/minvalue 限定的最大值位数更大,那么一个用户错误会被抛出。

创建自适应序列

首先创建一个noscale的序列,则跟常规序列一样,这个也是默认值。

检查当前的instance_id和sid

1
2
3
4
5
6
7
8
9
10
11
SQL> select sys_context('userenv','sid') from dual;

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

SQL> select instance_number from v$instance;

INSTANCE_NUMBER
---------------
1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
drop sequence my_seq;

create sequence my_seq
minvalue 1
maxvalue 9999999999
noscale;

SQL> select my_seq.nextval as scale_seq from dual;

SCALE_SEQ
----------
1

SQL> select my_seq.nextval as scale_seq from dual;

SCALE_SEQ
----------
2

增加SCALE属性,默认使用SCALE NOEXTEND,则会自动增加6位数的前缀,总长度则跟maxvalue的位数保持一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SQL> drop sequence my_seq;

Sequence dropped.

SQL>
SQL> create sequence my_seq
2 minvalue 1
3 maxvalue 9999999999
4 scale;

Sequence created.

SQL> select my_seq.nextval as scale_seq from dual;

SCALE_SEQ
----------
1013910001

SQL> select my_seq.nextval as scale_seq from dual;

SCALE_SEQ
----------
1013910002
  • 101为(instance_id % 100) + 100
  • 391为(session_id % 1000)

如果打开一个新的会话去执行,可以看到中间的部分会发生改变

1
2
3
4
5
6
7
8
9
10
11
12
13
SQL> select sys_context('userenv','sid') from dual;

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

SQL> select my_seq.nextval as scale_seq from dual;

SCALE_SEQ
----------
1015870003

SQL>

增加EXTEND关键字,这个时候前面的6位数前缀不变,而是增加长度与maxvalue的最大值长度相等的序列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SQL> col scale_seq for 999999999999999999
SQL> drop sequence my_seq;

Sequence dropped.

SQL>
SQL> create sequence my_seq
2 minvalue 1
3 maxvalue 9999999999
4 scale extend;

Sequence created.

SQL>
SQL>
SQL> select my_seq.nextval as scale_seq from dual;

SCALE_SEQ
-------------------
1013910000000001

SQL> select my_seq.nextval as scale_seq from dual;

SCALE_SEQ
-------------------
1013910000000002

变更自适应序列

可以直接对已存在的序列进行属性的修改

1
2
3
alter sequence my_seq noscale;
alter sequence my_seq scale noextend;
alter sequence my_seq scale extend;

查看已存在的自适应序列

1
2
3
4
5
6
7
8
9
10
11
12
13
column sequence_name format a30
column scale_flag format a10
column extend_flag format a10

select sequence_name,
scale_flag,
extend_flag
from user_sequences
where sequence_name = 'MY_SEQ';

SEQUENCE_NAME SCALE_FLAG EXTEND_FLA
------------------------------ ---------- ----------
MY_SEQ Y Y

Oracle自适应序列
https://www.xbdba.com/2024/08/14/scalable-sequences/
作者
xbdba
发布于
2024年8月14日
许可协议