PARALLEL Hint

PARALLEL Hint 是语句级的 Hint,用来指示优化器指定并行操作可使用的并行服务器的数量。此 Hint 将覆盖初始化参数 PARALLEL_DEGREE_ POLICY 的值。该 Hint 适用于语句的 SELECTINSERTMERGEUPDATEDELETE 部分,以及表扫描的部分。如果违反了任何的并行限制,则 PARALLEL Hint 被忽略。

以下是 PARALLEL Hint 的语法:

  1. /*+ PARALLEL [ ( DEFAULT | AUTO | MANUAL | integer ) ] */

注意

如果还进行了排序或分组操作,那么可以使用的服务器数量是 PARALLEL Hint 中的值的两倍。

PARALLEL Hint 中指定参数的值时:

  • PARALLEL:数据库计算并行度,可以为 2 或更大。语句一直并行执行。
  • PARALLEL(DEFAULT) :优化器计算的并行度等于所有参与实例上可用的 CPU 数量乘以初始化参数 PARALLEL_THREADS_PER_CPU 的值。
  • PARALLEL(AUTO) :数据库计算并行度,结果可以大于等于 1,如果计算出的并行度为 1,则该语句按顺序运行。
  • PARALLEL(MANUAL):优化器被强制使用语句中设置的对象的并行度。
  • PARALLEL(integer):优化器使用参数 integer 指定的整数值为并行度。

以下示例中数据库计算并行度,并且语句一直并行执行:

  1. SELECT /*+ PARALLEL */ last_name
  2. FROM employees;

以下示例中数据库计算并行度,但是并行度为 1,所以该语句串行执行:

  1. SELECT /*+ PARALLEL (AUTO) */ last_name
  2. FROM employees;

在以下示例中,PARALLEL Hint 建议优化器使用语句中设定的,当前对表本身有效的并行度 5:

  1. CREATE TABLE parallel_table (col1 number, col2 VARCHAR2(10)) PARALLEL 5;
  2. SELECT /*+ PARALLEL (MANUAL) */ col2
  3. FROM parallel_table;

USE_PX Hint

USE_PX Hint 强制指示服务器在执行 SQL 语句时使用 PX 模式,PX 模式允许在执行语句时采用多线程方式。一般 USE_PX Hint 和 PARALLEL Hint 配合使用。

以下是 USE_PX Hint 的语法:

  1. /*+ USE_PX */

示例如下:

  1. SELECT /*+ USE_PX PARALLEL(4)*/ e.department_id, sum(e.salary)
  2. FROM employees e
  3. WHERE e.department_id = 1001;
  4. GROUP BY e.department_id;

NO_USE_PX Hint

NO_USE_PX Hint 强制指示服务器在执行 SQL 语句时避免使用 PX 模式。

以下是 NO_USE_PX Hint 的语法:

  1. /*+ NO_USE_PX */

示例如下:

  1. SELECT /*+ NO_USE_PX*/ e.department_id, sum(e.salary)
  2. FROM employees e
  3. WHERE e.department_id = 1001;
  4. GROUP BY e.department_id;

PQ_DISTRIBUTE Hint

PQ_DISTRIBUTE Hint 指示优化器怎样在程序(查询)服务器和消耗(负载)查询服务器之间分配行。您可以通过该 Hint 控制联接或负载的行分布。

以下是 PQ_DISTRIBUTE Hint 的语法:

  1. /*+ PQ_DISTRIBUTE
  2. ( [ @ queryblock ] tablespec
  3. { distribution | outer_distribution inner_distribution }
  4. ) */

控制负载的分配

您可以控制并行语句 INSERT ... SELECT 和并行语句 CREATE TABLE ... AS SELECT 的行分布,以此来确定如何在程序(查询)服务器和消耗(负载)服务器之间进行行分配。使用语法的上分支来指定分发方法。分布方法的值及其语义如下表所示:

分布方法说明
NONE没有分配。即将查询和负载操作组合到每个查询服务器中。所有服务器将加载所有分区。这种分配方法的缺失有助于避免在没有偏离的情况下行分配的开销。由于空段或语句中的谓词会过滤掉查询评估的所有行,因此可能会发生偏离。如果由于使用此方法而发生偏斜,则请改用 RANDOMRANDOM_ LOCAL 分布。注意:请谨慎使用此分配方法。每个进程加载的 PGA 内存最少需要 512 KB。如果还使用压缩,则每台服务器消耗大约 1.5 MB 的 PGA 内存
PARTITION此方法使用 tablespec 的分区信息将行从查询服务器分发到消耗服务器。当不可能或不希望将查询和加载操作组合在一起时和当正在加载的分区数量大于或等于加载服务器的数量并且输入数据将均匀地分布在正在加载的分区之间(即没有偏离)时,请使用此分步方法。
RANDOM此方法以循环方式将来自程序的行分发给消耗。当输入数据高度倾斜时,使用这种分布方法。
RANDOM_LOCAL此方法将来自程序的行分布到一组服务器,这些服务器负责维护给定的一组服务器。两个或多个服务器可以加载同一分区,但是没有服务器加载所有分区。当输入数据发生偏移并且由于内存限制而无法合并查询和加载操作时,请使用此分布方法。

例如,在以下直接装入插入操作中,该操作的查询和负载部分被组合到每个查询服务器中:

  1. INSERT /*+ APPEND PARALLEL(target_table, 16) PQ_DISTRIBUTE(target_table, NONE) */
  2. INTO target_table
  3. SELECT * FROM source_table;

在下面的示例中,创建表时优化器使用表 target_table 的分区来分配行:

  1. CREATE /*+ PQ_DISTRIBUTE(target_table, PARTITION) */ TABLE target_table
  2. NOLOGGING PARALLEL 16
  3. PARTITION BY HASH (l_orderkey) PARTITIONS 512
  4. AS SELECT * FROM source_table;

控制联接的分配

您可以通过指定两种分配方法来控制联接的分配方法,如语法中的下部分支所示,一种外部表的分布方法,一种内部表的分布方法:

  • outside_distribution 是外部表的分布方法。
  • inner_distribution 是内部表的分布方法。

分布方法的值是 HASHBROADCASTPARTITIONNONE。只有下表中的 6 种分布方法组合是有效的:

分布方法说明
HASH, HASH使用联接键上的哈希函数,将每个表的行映射到消耗查询服务器。映射完成后,每个查询服务器都会在一对结果分区之间执行联接。当表的大小可比较并且联接操作是通过哈希联接或排序合并联接实现时,建议使用此分布方法。
BROADCAST, NONE外部表的所有行都广播到每个程序查询服务器。内部表行是随机分区的。当外部表与内部表相比非常小时,建议使用此分布方法。通常,当内部表大小乘以查询服务器的数量大于外部表大小时,也建议使用此分布方法。
NONE, BROADCAST内部表的所有行都广播给每个消耗查询服务器。外部表行是随机分区的。当内部表与外部表相比非常小时,建议使用此分布方法。通常,当内部表大小乘以查询服务器的数量小于外部表大小时,也建议使用此分布方法。
PARTITION, NONE外部表的行使用以内部表的分区进行映射。内部表必须在联接键上进行分区。当外部表的分区数等于或几乎等于查询服务器数的倍数时,建议使用此分布方法。例如,有 14 个分区和 15 个查询服务器。注意:如果内部表未分区或未在分区键上等分联接时,则优化器将忽略此 Hint。
NONE, PARTITION内部表的行使用外部表的分区进行映射。外部表必须在联接键上进行分区。当外部表的分区数等于或几乎等于查询服务器数的倍数时,建议使用此分布方法。例如,有 14 个分区和 15 个查询服务器。注意:如果外部表未在分区键上进行分区或未等分联时接,则优化器将忽略此 Hint。
NONE, NONE每个查询服务器在一对匹配的分区之间执行联接操作,每个表中都有一个。两个表必须在连接键上等分。

例如,给定两个使用哈希联接来联接表 rs,以下查询包含使用哈希分配的 Hint:

  1. SELECT /*+ORDERED PQ_DISTRIBUTE(s HASH, HASH) USE_HASH (s)*/ column_list
  2. FROM r,s
  3. WHERE r.c=s.c;

要广播外部表 r,查询语句为:

  1. SELECT /*+ORDERED PQ_DISTRIBUTE(s BROADCAST, NONE) USE_HASH (s) */ column_list
  2. FROM r,s
  3. WHERE r.c=s.c;