如何解决Oracle 中的 NOPARALLEL 和 PARALLEL 1 有什么区别?
noparaLLEL
和 ParaLLEL 1
有什么区别?如果我像这样创建三个表:
CREATE TABLE t0 (i NUMBER) noparaLLEL;
CREATE TABLE t1 (i NUMBER) ParaLLEL 1;
CREATE TABLE t2 (i NUMBER) ParaLLEL 2;
它们在数据字典中显示为
SELECT table_name,degree FROM user_tables WHERE table_name IN ('T0','T1','T2');
TABLE_NAME DEGREE
T0 1 <==
T1 1 <==
T2 2
然而,documentation 的表述非常清楚
noparaLLEL:为串行执行指定 noparaLLEL。这是默认设置。
ParaLLEL integer:整数的规格表示并行度,即并行操作中使用的并行线程数。每个并行线程可以使用一个或两个并行执行服务器。
所以,noparaLLEL
肯定是串行的,而 ParaLLEL 1
使用一个线程,可能使用一个或两个并行服务器???但是当数据字典为两者存储相同的值1时,Oracle如何区分它们?
顺便说一句,?/rdbms/admin/dcore.bsq 中的 CREATE TABLE sys.tab$
语句有评论
/*
* Legal values for degree,instances:
* NULL (used to represent 1 on disk/dictionary and implies noparallel),or
* 2 thru EB2MAXVAL-1 (user supplied values),or
* EB2MAXVAL (implies use default value)
*/
degree number,/* number of parallel query slaves per instance */
instances number,/* number of OPS instances for parallel query */
解决方法
NOPARALLEL
和 PARALLEL 1
之间没有区别 - 这些选项的存储方式和行为方式相同。这是一个文档错误,因为 Oracle 永远不会为 PARALLEL 1
使用两个并行执行服务器。我们可以通过查看 V$PX_PROCESS
和理解并行的生产者/消费者模型来测试这种情况。
如何测试并行性
有很多方法可以衡量并行度,例如执行计划或查看GV$SQL.USERS_EXECUTING
。但最好的方法之一是使用视图 GV$PX_PROCESS
。以下查询将显示当前使用的所有并行服务器:
select *
from gv$px_process
where status <> 'AVAILABLE';
生产者/消费者模型
VLDB 和分区指南的 Using Parallel Execution 一章值得一读,如果您想全面了解 Oracle 并行性。特别是,阅读手册的 Producer/Consumer Model 部分以了解 Oracle 何时会将并行服务器的数量增加一倍。
简而言之 - 每个操作都是单独并行执行的,但这些操作需要相互馈送数据。全表扫描可能使用 4 个并行服务器读取数据,但 group by 或 order by 操作需要另外 4 个并行服务器对数据进行散列或排序。而并行度是4,并行服务器的数量是8。这就是SQL语言参考中“每个并行线程可能使用一个或两个并行执行服务器”这句话的意思。
Oracle 不只是随机地将服务器数量增加一倍。加倍仅发生在某些操作(例如 ORDER BY
)上,这让我们可以在 Oracle 启用并行性时进行精确测试。以下测试表明 Oracle 不会将 1 个并行线程加倍到 2 个并行服务器。
测试
创建这三个表:
create table table_noparallel noparallel as select level a from dual connect by level <= 1000000;
create table table_parallel_1 parallel 1 as select level a from dual connect by level <= 1000000;
create table table_parallel_2 parallel 2 as select level a from dual connect by level <= 1000000;
运行以下查询,并在它们运行时使用单独的会话针对 GV$PX_PROCESS
运行先前的查询。在这里使用 IDE 可能会有所帮助,因为您只需检索前 N 行并保持游标打开即可算作使用并行服务器。
--0 rows:
select * from table_noparallel;
--0 rows:
select * from table_noparallel order by 1;
--0 rows:
select * from table_parallel_1;
--0 rows:
select * from table_parallel_1 order by 1;
--2 "IN USE":
select * from table_parallel_2;
--4 "IN USE":
select * from table_parallel_2 order by 1;
请注意,NOPARALLEL
和 PARALLEL 1
表的工作方式完全相同,并且都没有使用任何并行服务器。但是PARALLEL 2
表在排序结果时会导致并行执行服务器的数量翻倍。
为什么甚至允许PARALLEL 1
?
为什么 Oracle 不强制 PARALLEL
子句只接受大于 1 的数字并避免这种歧义?毕竟,编译器已经实施了限制;子句 PARALLEL 0
将引发错误“ORA-12813:PARALLEL 或 DEGREE 的值必须大于 0”。
我猜想允许数值表示“无并行性”可以使一些代码更简单。例如,我编写了计算 DOP 并作为变量传递的程序。如果只用数字,动态SQL就这么简单:
v_sql := 'create or replace table test1(a number) parallel ' || v_dop;
如果我们必须使用 NOPARALLEL
,代码会变得更难看:
if v_dop = 1 then
v_sql := 'create or replace table test1(a number) noparallel';
else
v_sql := 'create or replace table test1(a number) parallel ' || v_dop;
end if;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。