是否可以重新创建 Oracle 固定视图?我遇到 GV$ACTIVE_SESSION_HISTORY 的性能问题,可能需要重建视图。
select * from gv$active_session_history;
由于错误的执行计划,一个简单的永远运行。这只发生在我们的少数数据库上,可能与以前的 NLS 设置有关。下面的执行计划使用 2 个FIXED TABLE FULL
操作,因为NLSSORT
谓词阻止使用固定索引:
explain plan for select * from gv$active_session_history;
select * from table(dbms_xplan.display);
Plan hash value: 2432277601
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 136K| 169M| 215 (100)| 00:00:04 |
| 1 | VIEW | GV$ACTIVE_SESSION_HISTORY | 136K| 169M| 215 (100)| 00:00:04 |
| 2 | NESTED LOOPS | | 136K| 62M| 215 (100)| 00:00:04 |
| 3 | FIXED TABLE FULL| X$KEWASH | 136K| 3196K| 72 (100)| 00:00:02 |
|* 4 | FIXED TABLE FULL| X$ASH | 1 | 454 | 0 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("S"."SAMPLE_ADDR"="A"."SAMPLE_ADDR" AND "S"."SAMPLE_ID"="A"."SAMPLE_ID"
AND "S"."SAMPLE_TIME"="A"."SAMPLE_TIME" AND
NLSSORT("S"."NEED_AWR_SAMPLE",'nls_sort=''BINARY_CI''')=NLSSORT("A"."NEED_AWR_SAMPLE",'n
ls_sort=''BINARY_CI'''))
为了比较,这里有一个很好的执行计划,适用于我们 99% 的数据库:
Plan hash value: 436940376
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 100 | 127K| 0 (0)| 00:00:01 |
| 1 | VIEW | GV$ACTIVE_SESSION_HISTORY | 100 | 127K| 0 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 100 | 131K| 0 (0)| 00:00:01 |
| 3 | FIXED TABLE FULL | X$KEWASH | 100 | 5200 | 0 (0)| 00:00:01 |
|* 4 | FIXED TABLE FIXED INDEX| X$ASH (ind:1) | 1 | 1299 | 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("S"."SAMPLE_ADDR"="A"."SAMPLE_ADDR" AND "S"."SAMPLE_ID"="A"."SAMPLE_ID" AND
"S"."SAMPLE_TIME"="A"."SAMPLE_TIME" AND "S"."NEED_AWR_SAMPLE"="A"."NEED_AWR_SAMPLE")
这是我尝试过的方法,以及不起作用的解决方法:
- 提示和计划管理功能。 一次修复一个查询是不够的。这个固定视图在太多的系统查询中使用,我不想全部修改。例如,我可以用这样的提示修复我的示例:
select /*+ use_hash(@"SEL$3" "A"@"SEL$3") */ * from gv$active_session_history order by sample_time desc;
。但我无法更改使用 GV$* 的系统查询,而且我不想管理每个单独的查询。 - 收集统计数据。 “Rows = 1”表示统计数据不佳,但我已经尝试收集统计数据但无济于事。
- 伪造统计数据。 即使在将表行设置得高得离谱并将列设置得非常低之后,我也无法计划使用散列连接。即使优化器认为连接返回千万亿行,它仍然使用带有两次全表扫描的嵌套循环。
更改 NLS 设置。 起初,这看起来像是典型的语言排序忽略索引问题。但是 nls_sort 和 nls_comp 都设置为 BINARY。当我在会话级别更改 nls_comp 和 nls_sort 时,谓词有 2 个 NLSSORT 函数:
alter session set nls_comp='LINGUISTIC'; alter session set nls_sort='BINARY_CI'; explain plan for select * from gv$active_session_history where sql_id = '7f7bap53hb12w'; select * from table(dbms_xplan.display); ... Predicate Information (identified by operation id): --------------------------------------------------- 4 - filter(NLSSORT("A"."SQL_ID",'nls_sort=''BINARY_CI''')=HEXTORAW('37663762617035336 86231327700') AND "S"."SAMPLE_ADDR"="A"."SAMPLE_ADDR" AND "S"."SAMPLE_ID"="A"."SAMPLE_ID" AND "S"."SAMPLE_TIME"="A"."SAMPLE_TIME" AND NLSSORT("S"."NEED_AWR_SAMPLE",'nls_sort=''BINARY_CI''')=NLSSORT("A"."NEED_AWR_SAMPLE",'n ls_sort=''BINARY_CI'''))
当我将它们设置回 BINARY 时,其中一个 NLSSORT 消失了,但一个仍然存在,阻止了索引:
alter session set nls_comp='BINARY'; alter session set nls_sort='BINARY'; explain plan for select * from gv$active_session_history where sql_id = '7f7bap53hb12w'; select * from table(dbms_xplan.display); ... Predicate Information (identified by operation id): --------------------------------------------------- 4 - filter("A"."SQL_ID"='7f7bap53hb12w' AND "S"."SAMPLE_ADDR"="A"."SAMPLE_ADDR" AND "S"."SAMPLE_ID"="A"."SAMPLE_ID" AND "S"."SAMPLE_TIME"="A"."SAMPLE_TIME" AND NLSSORT("S"."NEED_AWR_SAMPLE",'nls_sort=''BINARY_CI''')=NLSSORT("A"."NEED_AWR_SAMPLE",'n ls_sort=''BINARY_CI'''))
找到视图源。 我找不到完整的视图源。它不在 DBA_VIEWS 中,只有前 4000 个字符在 $FIXED_VIEW_DEFINITION 中。我在 $ORACLE_HOME/rdbms/admin/ 中尝试过
grep -i v.*active_session_history *
,但没有看到任何东西。- 重新编译。
alter view gv$active_session_history compile;
抛出 ORA-600。
我在 Solaris 上运行 11.2.0.4。我创建了 Oracle 支持服务请求,但尚未收到答复。
假设您使用以下参数创建了数据库:
通过创建,我的意思是从头开始创建。DBCA 自定义数据库,或
CREATE DATABASE
手动运行和字典脚本。如果发生这种情况,这些将是您的数据库级别的 NLS 属性:
(默认情况下,您应该在这里看到
BINARY
和BINARY
,老实说,我不记得数据库有不同值的单一情况 - 除了我刚刚在我的沙箱中创建的那个。)鉴于上述情况,您将获得与问题中相同的执行计划。您可以重新启动实例,或者
NLS_COMP
在NLS_SORT
会话或系统(实例)级别将其设置为相同的值,它不会“修复”执行计划。要修改上述设置,从技术上讲可以(但永远不要在真实数据库中这样做)手动更新这些值(重新运行字典脚本不会更新它):
在此之后(以及关闭 + 启动),同一查询使用固定索引,而没有
NLSSORT
在过滤器中进行任何隐式调用。还原更改:
关机,启动,解释,dbms_xplan.display,又报错了。
另一个(麻烦,但至少支持)选项是使用默认 (
BINARY
,BINARY
) 值重新创建数据库。