View Merge 在安全控制上的變化,是 BUG 還是增強 ?
作者簡單介紹
黃瑋(Fuyuncat)資深 Oracle DBA,致力於資料庫底層技術的研究。其作品獲得廣大同行的高度評價。
個人站點 www.HelloDBA.com
什麼是 View Merge
View Merge 是 12C 引入的新特性,也是一種優化手段。當查詢中引用了 View 或 inline view 時,優化器能夠將主查詢中的查詢條件併入檢視其中去進行優化選擇以獲得代價最小的執行計劃。而假設檢視不屬於當前執行語句的使用者。View Merge 就可能存在潛在 OPTIMIZER_SECURE_VIEW_MERGING(預設是 TRUE)控制。
當執行語句的使用者缺乏對檢視的 MERGE VIEW 許可權。也沒有 MERGE ANY VIEW 許可權時。是否同意優化器進行 View Merge 優化。
View Merge 問題重現
wx_fmt=png&wxfrom=5&wx_lazy=1" referrerPolicy="no-referrer">
以下是一個安全控制導致語句未能正確選擇索引的演示。首先建立對應的測試使用者(demo)並授予對應的許可權。
SQL 程式碼例如以下:
SQL> conn / as sysdba
Connected.
SQL> drop user demo cascade;
User dropped.
SQL> create user demo identified by demo;
User created.
SQL> grant CREATE SYNONYM,UNLIMITED TABLESPACE to demo;
Grant succeeded.
SQL> grant CONNECT,PLUSTRACE,RESOURCE to demo;
Grant succeeded.
建立對應的測試函式。
SQL 程式碼例如以下:
SQL> conn demo/demo
Connected.
SQL> create or replace FUNCTION fnCheckNumber(in_num IN VARCHAR2) RETURN NUMBER IS
2 BEGIN
3 return 1;
4 end;
5 /
Function created.
建立測試使用者 demo 2。授予連線與 resource 的許可權。
SQL 程式碼例如以下:
SQL> conn / as sysdba
Connected.
SQL> drop user demo2 cascade;
User dropped.
SQL> create user demo2 identified by demo2;
User created.
SQL> grant create session, resource to demo2;
Grant succeeded.
SQL> alter user demo2 default tablespace lmt_data;
User altered.
SQL> alter user demo2 quota unlimited on lmt_data;
User altered.
SQL> grant create view to demo2;
Grant succeeded.
SQL> drop user demo2 cascade;
User dropped.
建立測試表 t1。t2 以及測試檢視 v1,v2。並往表中增加測試資料,同一時候授予 demo 訪問的許可權。
SQL 程式碼例如以下:
SQL>conn demo2/demo2
Connected.
SQL> create table t1 as select * from all_tables;
Table created.
SQL> create table t2 as select * from all_objects;
Table created.
SQL> create unique index t2_idx1 on t2(object_id) compute statistics;
Index created.
SQL> create view v1 as select * from t1;
View created.
SQL> create view v2 as select * from t2;
View created.
SQL> grant select on t1 to demo;
Grant succeeded.
SQL> grant select on t2 to demo;
Grant succeeded.
SQL> grant select on v1 to demo;
Grant succeeded.
SQL> grant select on v2 to demo;
Grant succeeded.
將 share pool 曾經儲存的 SQL 執行計劃所有清空。釋放少數的共享池資源,保證 SQL 執行計劃的又一次解析。
SQL 程式碼例如以下:
SQL> conn / as sysdba
Connected.
SQL> alter system flush shared_pool;
System altered.
檢視執行計劃。
SQL 程式碼例如以下:
SQL> conn demo/demo
Connected.
SQL> set autot trace
SQL> select fnCheckNumber(tablespace_name) from demo2.v1
union all
select 1 from demo2.v2 where object_id = fnCheckNumber('567785951');
106 rows selected.
Execution Plan
----------------------------------------------
Plan hash value: 3515064724
-------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------
| 0 | SELECT STATEMENT | | 75158 | 953K| 40 (3)| 00:00:01 |
| 1 | UNION-ALL | | | | | |
| 2 | TABLE ACCESS FULL | T1 | 106 | 530 | 3 (0)| 00:00:01 |
|* 3 | VIEW | V2 | 75052 | 952K| 37 (3)| 00:00:01 |
| 4 | INDEX FAST FULL SCAN| T2_IDX1 | 75052 | 439K| 37 (3)| 00:00:01 |
-----------------------------------------------
Predicate Information (identified by operation id):
--------------------------------------
3 - filter("OBJECT_ID"="FNCHECKNUMBER"('567785951'))
Statistics
----------------------------------------
661 recursive calls
2 db block gets
501 consistent gets
163 physical reads
0 redo size
2428 bytes sent via SQL*Net to client
629 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
33 sorts (memory)
0 sorts (disk)
106 rows processed
獲取正確的索引訪問方式
在上面的查詢計劃中,未能正確選擇索引訪問方式。當我們賦予使用者 MERGE VIEW 許可權(或改動 OPTIMIZER_SECURE_VIEW_MERGING 為 FALSE)後,執行計劃獲取到了正確的索引訪問方式。
授權的 SQL 程式碼例如以下:
SQL> conn / as sysdba
Connected.
SQL> grant MERGE ANY VIEW to demo;
Grant succeeded.
再對 share pool 中原有的執行計劃進行清空一次,便於又一次解析。
詳細的 SQL 程式碼例如以下:
SQL> alter system flush shared_pool;
System altered.
對上面語句再解析一遍,獲取該語句的執行計劃。
詳細 SQL 程式碼與執行計劃例如以下:
SQL> set autot trace
SQL> select fnCheckNumber(tablespace_name) from demo2.v1 union all
select 1 from demo2.v2 where object_id = fnCheckNumber('567785951');
106 rows selected.
Execution Plan
-----------------------------------------------
Plan hash value: 809018835
---------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 536 | 4 (0)| 00:00:01 |
| 1 | UNION-ALL | | | | | |
| 2 | TABLE ACCESS FULL| T1 | 106 | 530 | 3 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN| T2_IDX1 | 1 | 6 | 1 (0)| 00:00:01 |
-----------------------------------------------------
Predicate Information (identified by operation id):
-----------------------------------------------
3 - access("OBJECT_ID"="FNCHECKNUMBER"('567785951'))
Statistics
------------------------------------------
680 recursive calls
2 db block gets
340 consistent gets
0 physical reads
0 redo size
2428 bytes sent via SQL*Net to client
629 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
33 sorts (memory)
0 sorts (disk)
106 rows processed
能夠看到上面的執行計劃已經正確選擇索引訪問方式了。
改動 optimizer_secure_view_merging 引數。
SQL 程式碼例如以下:
SQL> show parameter optimizer_secure_view_merging
NAME TYPE VALUE
-------------------------- ----------- -----------------------
optimizer_secure_view_merging boolean TRUE
SQL> alter system set optimizer_secure_view_merging =false;
System altered.
研究收穫
從上面的案例能夠分析出 View Merge 是 12C 的一個新特性。由於這個安全控制導致在查詢計劃中未能正確選擇索引訪問方式,僅僅須要取消掉這個新特性或者將 MERGE ANY VIEW 授予使用者後就能夠得到對應正確的索引訪問方式。
資源下載
關注公眾號:資料和雲(OraNews)回覆keyword獲取
‘2017DTC’,2017 DTC 大會 PPT
‘DBALIFE’,“DBA 的一天”海報
‘DBA04’,DBA 手記4 經典篇章電子書
‘RACV1’, RAC 系列課程視訊及 PPT
‘122ARCH’,Oracle 12.2 體系結構圖
‘2017OOW’,Oracle OpenWorld 資料
‘PRELECTION’。大講堂講師課程資料