Oracle 中的 NOPARALLEL 和 PARALLEL 1 有什么区别?

问题描述

noparaLLELParaLLEL 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 */

解决方法

NOPARALLELPARALLEL 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;

请注意,NOPARALLELPARALLEL 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;

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...