2

有一段时间我一直在努力抽出时间来写这个问题并尽可能地解释这个问题,所以请提前原谅我的长文。

我的环境:

  • 在 Red Hat 7(RAC 2 节点)上运行的 Oracle Database 12.2 - 每个节点 16CPU 和 64GB RAM。
  • Parallel Force Local 设置为 TRUE 以强制并行服务器进程只能在启动 SQL 语句的同一节点上执行。

我们有一个非常大的数据库,其中包含许多服务于多个应用程序的模式。大多数应用程序实际上是 PL/SQL 中的批处理引擎,处理亿万条记录,因此出于性能原因,大多数大表都配置了 PARALLEL DEGREE DEFAULT。表已分区并具有高级压缩。

除了一些用于开发目的的报告 BI 工具外,许多最终用户还可以通过 SQL Developer 访问系统(仅在读取模式下)以进行 QA 检查。我从不喜欢,但有时你必须接受事情的本来面目。

为了控制一些事情,我设计了一个特定的登录触发器,它不仅涵盖了审计功能,还涵盖了传入会话的某些方面:

  • 使用 SQL Developer 访问的最终用户可能只打开 2 个会话。
  • 使用 SQL Developer 访问的最终用户运行立即执行 ALTER SESSION DISABLE PARALLEL QUERY。不幸的是,我知道有些用户正在自己激活它。ALTER SESSION ENABLE/DISABLE PARALLEL QUERY 是由 CREATE SESSION 权限或 CONNECT 角色继承的,所以我对此无能为力。
  • 使用 SQL Developer 访问的最终用户被分配到一个特定的配置文件,该配置文件在 CPU、磁盘读取等方面有限制。

登录触发器允许或不允许基于一组附加规则的访问,但出于问题的目的,它们并不重要。

让我们看看在 SQL Developer 上运行的查询如何针对启用了 PARALLEL 的表表现:

设想

我有一个包含 80 亿条记录的表,这些记录被不同的分区分割。用户使用 sql developer 登录并运行此查询

SELECT COUNT(*) FROM MY_SCHEMA.MY_TABLE PARTITION ( MY_PARTITION ) ;

183.940.801 rows 

由于该表没有索引,因此 CBO 在 PARALLEL 中运行 TABLE FULL SCAN,使用尽可能多的从属设备。完成需要 6 秒。到目前为止,没有错。

同时我正在监视会话(查询运行时您可以看到所有活动的会话)

  INSTANCE     SID USERNAME             PROGRAM                                            SQL_ID               STATUS
---------- ------- -------------------- -------------------------------------------------- -------------------- --------
         2       6 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00N)       dtf8d89xg7muq        ACTIVE
         2     128 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P004)       dtf8d89xg7muq        ACTIVE
         2     140 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P007)       dtf8d89xg7muq        ACTIVE
         2     256 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00O)       dtf8d89xg7muq        ACTIVE
         2     284 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00D)       dtf8d89xg7muq        ACTIVE
         2     388 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00C)       dtf8d89xg7muq        ACTIVE
         2     400 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00P)       dtf8d89xg7muq        ACTIVE
         2     510 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00E)       dtf8d89xg7muq        ACTIVE
         2     621 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00F)       dtf8d89xg7muq        ACTIVE
         2     641 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00Q)       dtf8d89xg7muq        ACTIVE
         2     739 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P008)       dtf8d89xg7muq        ACTIVE
         2     771 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P005)       dtf8d89xg7muq        ACTIVE
         2     888 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00R)       dtf8d89xg7muq        ACTIVE
         2     893 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00G)       dtf8d89xg7muq        ACTIVE
         2     996 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00H)       dtf8d89xg7muq        ACTIVE
         2    1010 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00S)       dtf8d89xg7muq        ACTIVE
         2    1015 FDM_ADM_GRID         SQL Developer                                      dtf8d89xg7muq        ACTIVE
         2    1109 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00T)       dtf8d89xg7muq        ACTIVE
         2    1116 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00I)       dtf8d89xg7muq        ACTIVE
         2    1230 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00J)       dtf8d89xg7muq        ACTIVE
         2    1254 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00U)       dtf8d89xg7muq        ACTIVE
         2    1352 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P009)       dtf8d89xg7muq        ACTIVE
         2    1376 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P001)       dtf8d89xg7muq        ACTIVE
         2    1383 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P006)       dtf8d89xg7muq        ACTIVE
         2    1477 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00V)       dtf8d89xg7muq        ACTIVE
         2    1488 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P000)       dtf8d89xg7muq        ACTIVE
         2    1506 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00K)       dtf8d89xg7muq        ACTIVE
         2    1604 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P002)       dtf8d89xg7muq        ACTIVE
         2    1617 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00L)       dtf8d89xg7muq        ACTIVE
         2    1620 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00A)       dtf8d89xg7muq        ACTIVE
         2    1740 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P003)       dtf8d89xg7muq        ACTIVE
         2    1743 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00M)       dtf8d89xg7muq        ACTIVE
         2    1851 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00B)       dtf8d89xg7muq        ACTIVE
        

查询完成后

SQL> r
  1* select inst_id as instance , sid, username, program, sql_id, status from gv$session where username = 'FDM_ADM_GRID'

  INSTANCE     SID USERNAME             PROGRAM                                            SQL_ID               STATUS
---------- ------- -------------------- -------------------------------------------------- -------------------- --------
         2    1015 FDM_ADM_GRID         SQL Developer                                                           INACTIVE
        

到现在为止还挺好。现在让我们在 SQL Developer 中运行另一个查询

SELECT * FROM MY_SCHEMA.MY_TABLE partition ( MY_PARTITION ) fetch first 1000 rows only;

该查询几乎立即检索前 1000 行。但是让我们看看数据库的区别

当它运行时

SQL> r
  1* select inst_id as instance , sid, username, program, sql_id, status from gv$session where username = 'FDM_ADM_GRID'

  INSTANCE     SID USERNAME             PROGRAM                                            SQL_ID               STATUS
---------- ------- -------------------- -------------------------------------------------- -------------------- --------
         2       6 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00N)       9jyvj64ag15mv        ACTIVE
         2     128 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P007)       9jyvj64ag15mv        ACTIVE
         2     140 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P004)       9jyvj64ag15mv        ACTIVE
         2     256 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00D)       9jyvj64ag15mv        ACTIVE
         2     284 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00O)       9jyvj64ag15mv        ACTIVE
         2     388 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00P)       9jyvj64ag15mv        ACTIVE
         2     400 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00C)       9jyvj64ag15mv        ACTIVE
         2     510 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00E)       9jyvj64ag15mv        ACTIVE
         2     621 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00F)       9jyvj64ag15mv        ACTIVE
         2     641 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00Q)       9jyvj64ag15mv        ACTIVE
         2     739 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P008)       9jyvj64ag15mv        ACTIVE
         2     771 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P005)       9jyvj64ag15mv        ACTIVE
         2     888 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00G)       9jyvj64ag15mv        ACTIVE
         2     893 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00R)       9jyvj64ag15mv        ACTIVE
         2     996 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00H)       9jyvj64ag15mv        ACTIVE
         2    1010 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00S)       9jyvj64ag15mv        ACTIVE
         2    1015 FDM_ADM_GRID         SQL Developer                                                           ACTIVE
         2    1109 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00I)       9jyvj64ag15mv        ACTIVE
         2    1116 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00T)       9jyvj64ag15mv        ACTIVE
         2    1230 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00J)       9jyvj64ag15mv        ACTIVE
         2    1254 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00U)       9jyvj64ag15mv        ACTIVE
         2    1352 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P006)       9jyvj64ag15mv        ACTIVE
         2    1376 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P009)       9jyvj64ag15mv        ACTIVE
         2    1383 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P001)       9jyvj64ag15mv        ACTIVE
         2    1477 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P000)       9jyvj64ag15mv        ACTIVE
         2    1488 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00V)       9jyvj64ag15mv        ACTIVE
         2    1506 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00K)       9jyvj64ag15mv        ACTIVE
         2    1604 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P002)       9jyvj64ag15mv        ACTIVE
         2    1617 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00A)       9jyvj64ag15mv        ACTIVE
         2    1620 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00L)       9jyvj64ag15mv        ACTIVE
         2    1740 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P003)       9jyvj64ag15mv        ACTIVE
         2    1743 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00M)       9jyvj64ag15mv        ACTIVE
         2    1851 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00B)       9jyvj64ag15mv        ACTIVE

查询完成后,我再次检查,但现在所有从属设备仍然存在并且处于活动状态。我会认为,一旦 QC 完成并标记为非活动状态,Oracle 就会关闭所有从属进程。但它没有

  `INSTANCE     SID USERNAME             PROGRAM`                                            SQL_ID               STATUS
---------- ------- -------------------- -------------------------------------------------- -------------------- --------
     2       6 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00N)       9jyvj64ag15mv        ACTIVE
     2     128 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P007)       9jyvj64ag15mv        ACTIVE
     2     140 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P004)       9jyvj64ag15mv        ACTIVE
     2     256 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00D)       9jyvj64ag15mv        ACTIVE
     2     284 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00O)       9jyvj64ag15mv        ACTIVE
     2     388 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00P)       9jyvj64ag15mv        ACTIVE
     2     400 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00C)       9jyvj64ag15mv        ACTIVE
     2     510 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00E)       9jyvj64ag15mv        ACTIVE
     2     621 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00F)       9jyvj64ag15mv        ACTIVE
     2     641 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00Q)       9jyvj64ag15mv        ACTIVE
     2     739 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P008)       9jyvj64ag15mv        ACTIVE
     2     771 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P005)       9jyvj64ag15mv        ACTIVE
     2     888 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00G)       9jyvj64ag15mv        ACTIVE
     2     893 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00R)       9jyvj64ag15mv        ACTIVE
     2     996 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00H)       9jyvj64ag15mv        ACTIVE
     2    1010 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00S)       9jyvj64ag15mv        ACTIVE
     2    1015 FDM_ADM_GRID         SQL Developer                                                           INACTIVE
     2    1109 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00I)       9jyvj64ag15mv        ACTIVE
     2    1116 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00T)       9jyvj64ag15mv        ACTIVE
     2    1230 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00J)       9jyvj64ag15mv        ACTIVE
     2    1254 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00U)       9jyvj64ag15mv        ACTIVE
     2    1352 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P006)       9jyvj64ag15mv        ACTIVE
     2    1376 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P009)       9jyvj64ag15mv        ACTIVE
     2    1383 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P001)       9jyvj64ag15mv        ACTIVE
     2    1477 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P000)       9jyvj64ag15mv        ACTIVE
     2    1488 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00V)       9jyvj64ag15mv        ACTIVE
     2    1506 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00K)       9jyvj64ag15mv        ACTIVE
     2    1604 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P002)       9jyvj64ag15mv        ACTIVE
     2    1617 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00A)       9jyvj64ag15mv        ACTIVE
     2    1620 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00L)       9jyvj64ag15mv        ACTIVE
     2    1740 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P003)       9jyvj64ag15mv        ACTIVE
     2    1743 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00M)       9jyvj64ag15mv        ACTIVE
     2    1851 FDM_ADM_GRID         oracle@scglvdoraci0010.scger.pre.corp (P00B)       9jyvj64ag15mv        ACTIVE
     

只要会话保持打开状态,QC 将保持非活动状态,从属服务器处于活动状态,因此尽管它们不做任何事情,但它们仍然算作并行服务器。会话关闭或用户运行另一个查询让我注意到并行使用的变化。但是如果用户去喝咖啡,或者去发射或者正在做其他事情,就不会有任何东西。有 100 多个用户同时工作,您可能会想象到头痛。我不得不设计一些解决方法:

  • 我必须在触发器内创建一个新控件来识别 QC 与处于 ACTIVE 状态的从属设备的非活动时间,以便确定用户已经打开了多少会话。
  • 在 1 小时的窗口时间后,我必须创建一个清理过程以断开处于此状态的会话
  • 我不能在配置文件中使用限制会话,因为它们在 QC 或 SLAVES 之间没有区别。
  • 无论我配置了多少东西,有时我会用完并行进程,并且如果在工作时间执行批处理(这种情况经常发生),我有时会面临这些重要进程缺乏并行可用性的问题,因为非活动会话。

我的问题如下:

  • 为什么当 QC 已经完成时,slave 仍然处于 ACTIVE 状态?不应该在 QC 交付结果后立即终止从站吗?
  • 为什么在 SQLPLUS 和 Java 池解决方案(作为 SAP 业务对象)中运行非常相似的查询时不会发生这种行为?
  • 有没有办法禁用最终用户的并行功能,无论他们尝试通过 ENABLE PARALLEL QUERY 还是通过 HINTS 来激活它们?

我为这个冗长的问题道歉,但我不想留下任何东西。我真的很感激对此的任何见解。

谢谢你们。

4

1 回答 1

2

您的查询并未真正完成。尽管您的查询仅获取前 1000 行,但 SQL Developer 仅获取这 1000 行中的前 50 行。在您滚动到最后一行之前,IDE 不会关闭游标。一旦您检索到所有数据,这些并行过程就会消失。确保您看到“All Rows Fetched: 1000 in X seconds”,而不是“”Fetched 50 rows in Y seconds”。(我希望 SQL Developer 能够更直观地看到还有其他行在等待。)你不会在 SQL*Plus 中看到这个问题,因为 SQL*Plus 总是抓取所有的行。

当仅获取前 N 行时,这些并行进程处于“活动”状态,但不执行任何操作。您应该能够忽略这些会话,因为它们没有使用任何重要资源。

如果您只担心并行会话的数量,您可能需要调整您的期望。我曾经和你处于同样的情况——不断地告诉用户他们的(不完整的)查询占用了所有并行会话。最终,我发现这只是一个问题,因为我创造了一种人为的稀缺资源。Oracle 并行进程通常是轻量级的,并且数据库可以支持比大多数人认为的更多的并行进程。

PARALLEL_MAX_SERVERS、PARALLEL_THREADS_PER_CPU 和 CPU_COUNT 的参数值是多少?查看PARALLEL_MAX_SERVERS的默认值。根据手册,默认编号为:PARALLEL_MAX_SERVERS = PARALLEL_THREADS_PER_CPU * CPU_COUNT * concurrent_parallel_users * 5.

大多数 DBA 看到最大数量的并行线程数以百计,恐慌,然后减少该数量。然后我们开始对开发人员大喊大叫,因为他们使用了人为限制的不重要资源。相反,我们应该将数字调回默认值,而忽略随机并行会话。如果用户没有超过 IO 或 CPU 限制,那么他们使用多少并行线程并不重要。

(除了防止大量并行查询会话使用的可能例外。将您的用户放在不同的配置文件中,并将他们的 SESSIONS_PER_USER 设置为几十个。不要将其限制为 1 或 2 个。IDE 需要多个选项卡、后台进程的额外会话获取元数据和调试会话。如果您将限制设置为 2,您的开发人员将无法正确使用 IDE。)


编辑(回复评论)

我不确定您是否可以深入了解query coordinator的状态。QC 做了几件事,但理想情况下,它大部分时间都是空闲的,而并行会话处理大部分工作。

使用生产者/消费者模型,一半的并行会话可能正在接收数据,但实际上并没有做任何事情——就像它们只是某些操作中的内存结构一样。并行会话可能会在活动和非活动之间切换,因为并非所有步骤都需要尽可能多的会话。但我们不希望 Oracle 在中间关闭会话,因为以后可能需要它们,我们不想浪费时间打开和关闭会话。

影响并行度的因素有很多,但据我所知,增加 PARALLEL_MAX_SERVERS 不会影响单个语句请求的并行服务器数量。(但如果该语句已经要求比最大值更多的服务器,增加参数可能会影响分配的会话数)。

可能感觉 SQL 语句只是随机抓取所有并行会话,但最终 DOP 计算几乎总是遵循确定性规则。只是规则如此复杂,很难说它是如何运作的。例如,一个常见的混淆点是,每当查询添加排序或分组时,并行会话的数量就会增加一倍。

于 2020-07-24T23:18:55.003 回答