Oracle

重新創建固定視圖

  • August 6, 2018

是否可以重新創建 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")

這是我嘗試過的方法,以及不起作用的解決方法:

  1. 提示和計劃管理功能。 一次修復一個查詢是不夠的。這個固定視圖用在太多的系統查詢中,我不想全部修改。例如,我可以使用如下提示修復我的範例select /*+ use_hash(@"SEL$3" "A"@"SEL$3") */ * from gv$active_session_history order by sample_time desc;:但我無法更改使用 GV$* 的系統查詢,並且我不想管理每個單獨的查詢。
  2. 收集統計數據。 “Rows = 1”意味著統計數據不好,但我已經嘗試收集統計數據,但沒有幫助。
  3. 偽造統計數據。 即使在將表行設置得非常高並且將列設置得很低之後,我也無法制定使用雜湊聯接的計劃。即使優化器認為連接返回數万億行,它仍然使用帶有兩個全表掃描的嵌套循環。
  4. 更改 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'''))
  1. 找到視圖源。 我找不到完整的視圖源。它不在 DBA_VIEWS 中,只有前 4000 個字元在 $FIXED_VIEW_DEFINITION 中。我在 $ORACLE_HOME/rdbms/admin/ 中嘗試過grep -i v.*active_session_history *,但什麼也沒看到。
  2. 重新編譯。 alter view gv$active_session_history compile;拋出 ORA-600。

我在 Solaris 上執行 11.2.0.4。我創建了一個 Oracle 支持服務請求,但尚未收到答复。

假設您使用以下參數創建了數據庫:

NLS_COMP=LINGUISTIC
NLS_SORT=BINARY_CI

我所說的創造,真正的意思是從頭開始創造。DBCA 自定義數據庫,或CREATE DATABASE手動執行和字典腳本。

如果發生這種情況,這些將是您的數據庫級 NLS 屬性:

SQL> select * from nls_database_parameters 
    where parameter in ('NLS_COMP', 'NLS_SORT') 
    order by parameter;

PARAMETER  VALUE
---------- ----------
NLS_COMP   LINGUISTIC
NLS_SORT   BINARY_CI

(預設情況下,您應該看到BINARYand BINARY,老實說,我不記得數據庫具有不同值的單個案例 - 除了我剛剛在我的沙箱中創建的那個。)

鑑於上述情況,您將獲得與您的問題相同的執行計劃。您可以重新啟動實例,或者在會話或系統(實例)級別設置NLS_COMP和設置NLS_SORT相同的值,它不會“修復”執行計劃。

要修改上述設置,技術上可以(但永遠不要在真實數據庫中這樣做)手動更新這些值(重新執行字典腳本不會更新):

SQL> update props$ set value$ = 'BINARY' where name in ('NLS_COMP', 'NLS_SORT');

2 rows updated.

SQL> commit;

Commit complete.

在此之後(以及關閉 + 啟動),相同的查詢使用了固定索引,而過濾器中沒有任何隱式NLSSORT呼叫。

還原更改:

SQL> update props$ set value$ = 'BINARY_CI' where name in ('NLS_SORT');

1 row updated.

SQL> update props$ set value$ = 'LINGUISTIC' where name in ('NLS_COMP');

1 row updated.

SQL> commit;

關機,開機,解釋,dbms_xplan.display,又錯了。

另一個(麻煩,但至少受支持)選項是使用預設 ( BINARY, BINARY) 值重新創建數據庫。

引用自:https://dba.stackexchange.com/questions/118478