Is it possible to recreate Oracle fixed views? I have a performance problem with GV$ACTIVE_SESSION_HISTORY that might require rebuilding the view.
A simple select * from gv$active_session_history;
runs forever because of a bad execution plan. This only happens on a small number of our databases and probably has something to do with previous NLS settings. The below execution plan uses 2 FIXED TABLE FULL
operations, because the NLSSORT
predicate prevents a fixed index from being used:
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'''))
For comparison, here is a good execution plan on 99% of our databases:
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")
Here is what I've tried, and workarounds that don't work:
- Hints and plan management features. Fixing queries one-at-a-time isn't good enough. This fixed view is used in too many system queries, I don't want to modify them all. For example, I can fix my example with a hint like this:
select /*+ use_hash(@"SEL$3" "A"@"SEL$3") */ * from gv$active_session_history order by sample_time desc;
. But I can't change the system queries that use GV$*, and I don't want to have to manage each individual query. - Gathering statistics. "Rows = 1" implies bad statistics, but I've already tried gathering statistics and it doesn't help.
- Faking statistics. I couldn't get the plan to use a hash join even after setting the table rows ridiculously high and setting the column distinct low. Even when the optimizer thinks the join returns quadrillions of rows it still uses a nested loop with two full table scans.
Changing NLS settings. At first this looks like the typical linguistic-sorting-ignoring-index issue. But nls_sort and nls_comp are both set to BINARY. When I change nls_comp and nls_sort at the session level, the predicate has 2 NLSSORT functions:
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'''))
When I set them back to BINARY one of the NLSSORT goes away, but one remains, preventing the index:
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'''))
Find the view source. I can't find the full view source. It's not in DBA_VIEWS and only the first 4000 characters is in $FIXED_VIEW_DEFINITION. I tried
grep -i v.*active_session_history *
in $ORACLE_HOME/rdbms/admin/ but didn't see anything.- Recompile.
alter view gv$active_session_history compile;
throws an ORA-600.
I'm running 11.2.0.4 on Solaris. I created an Oracle support service request but have not received an answer yet.
alter session set optimizer_mode=RULE
. And by "gathering statistics" you meanDBMS_STATS.GATHER_FIXED_OBJECTS_STATS
right?DBMS_STATS.GATHER_FIXED_OBJECT_STATS
changed the plan.alter system flush shared_pool;
doesn't help. Maybe a restart with the (now) correct parameters is my only hope. It may take a while before I have permission to restart. I'll let you know what happens. Thanks for your help.