有一段时间我一直在努力抽出时间来写这个问题并尽可能地解释这个问题,所以请提前原谅我的长文。
我的环境:
- 在 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 来激活它们?
我为这个冗长的问题道歉,但我不想留下任何东西。我真的很感激对此的任何见解。
谢谢你们。