1. 程式人生 > 其它 >Oracle-引數學習_no_or_expansion

Oracle-引數學習_no_or_expansion

一、需求,某客戶問_no_or_expansion=TRUE 這個引數幹啥用的?是否建議在11.2.0.4環境上設定?

需求如上,那麼我們首先了解一下這個引數是幹啥的? 另外就是探索為什麼客戶以前的DBA設定這個引數? 非預設隱含引數

二、引數說明

2.1 引數含義

參考一個網站的論壇
https://community.oracle.com/mosc/discussion/3058861/no-or-expansion-parameter

說的很清楚!

Or expansion is a kind of query transformation that converts OR to UNION.
Say you have a query
select * from emp where id=1 OR name='Vishal' Oracle may choose to expand this OR condition , break this SQL into two pieces using a UNION clause. New transformed query would look like select * from emp where id=1 UNION select * from emp where name='Vishal'
就是Oracle內部是否會將Or 轉換為union 進行展開! 預設展開,True引數設定後,則不允許展開

2.2 引數測試對比

未建立索引前,觀察設定引數後,執行計劃和引數預設false一樣,沒啥子區別!

--------------------------------------------------------------------------------
_no_or_expansion
FALSE
OR expansion during optimization disabled

alter session set "_no_or_expansion"=true;
set linesize 500
set termout off
alter session set statistics_level=all;
select * from scott.emp where EMPNO=7782 OR ename='FORD'; select * from table(dbms_xplan.display_cursor(null,null,'ADVANCED ALLSTATS LAST PEEKED_BINDS')); -------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | -------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 2 |00:00:00.01 | 7 | |* 1 | TABLE ACCESS FULL| EMP | 1 | 2 | 76 | 3 (0)| 00:00:01 | 2 |00:00:00.01 | 7 | Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 / EMP@SEL$1 ----------------------------------------------------------------- BEGIN_OUTLINE_DATA IGNORE_OPTIM_EMBEDDED_HINTS OPTIMIZER_FEATURES_ENABLE('11.2.0.4') DB_VERSION('11.2.0.4') ALL_ROWS OUTLINE_LEAF(@"SEL$1") FULL(@"SEL$1" "EMP"@"SEL$1") END_OUTLINE_DATA */ 1 - filter(("EMPNO"=7782 OR "ENAME"='FORD')) Column Projection Information (identified by operation id): ----------------------------------------------------------- 1 - "EMPNO"[NUMBER,22], "ENAME"[VARCHAR2,10], "EMP"."JOB"[VARCHAR2,9], "EMP"."MGR"[NUMBER,22], "EMP"."HIREDATE"[DATE,7], "EMP"."SAL"[NUMBER,22], "EMP"."COMM"[NUMBER,22], "EMP"."DEPTNO"[NUMBER,22]

再次觀察這個引數啥子作用?

"或"的擴張。
使用"or"連線由不同欄位構成的查詢條件下,按照查詢條件將整個查詢分為多個獨立的查詢,為各個獨立查詢制定最優查詢路徑,然後查詢完的結果再組合起來。這叫“或的擴張”。當然,只有當使用or的各個查詢條件為驅動查詢條件時,並且or連線的是不同的欄位,才能制定這樣的執行計劃,否則,會走全表掃然後然後將or的查詢條件當過濾用途,當然還可能選擇將rowid走bitmap or,後面有介紹。
_no_or_expansion引數,預設false,true的話會禁止“或的擴張” /*+use_concat*/是想使用或擴張的hint

建立索引!!! or兩個欄位都建立索引,在觀察對比

SQL> create index scott.id on scott.emp(empno);
create index scott.id on scott.emp(empno)
                                   *
ERROR at line 1:
ORA-01408: such column list already indexed
SQL> create index scott.name_ind on scott.emp(ename);

引數調整為非預設true,這種情況引數如果有效果,則無法使用兩個索引進行彙總聚合返回結果

alter system set "_no_or_expansion"=true;
set linesize 500
set termout off
alter session set statistics_level=all;
select * from scott.emp where EMPNO=7782 OR ename='FORD';
select * from table(dbms_xplan.display_cursor(null,null,'ADVANCED ALLSTATS LAST PEEKED_BINDS'));
---------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name     | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |          |      1 |        |       |     3 (100)|          |      2 |00:00:00.01 |       4 |
|   1 |  TABLE ACCESS BY INDEX ROWID     | EMP      |      1 |      2 |    76 |     3   (0)| 00:00:01 |      2 |00:00:00.01 |       4 |
|   2 |   BITMAP CONVERSION TO ROWIDS    |          |      1 |        |       |            |          |      2 |00:00:00.01 |       2 |
|   3 |    BITMAP OR                     |          |      1 |        |       |            |          |      1 |00:00:00.01 |       2 |
|   4 |     BITMAP CONVERSION FROM ROWIDS|          |      1 |        |       |            |          |      1 |00:00:00.01 |       1 |
|*  5 |      INDEX RANGE SCAN            | PK_EMP   |      1 |        |       |     0   (0)|          |      1 |00:00:00.01 |       1 |
|   6 |     BITMAP CONVERSION FROM ROWIDS|          |      1 |        |       |            |          |      1 |00:00:00.01 |       1 |
|*  7 |      INDEX RANGE SCAN            | NAME_IND |      1 |        |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       1 |
---------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access("EMPNO"=7782)
   7 - access("ENAME"='FORD')

引數預設不調整的情況下

alter system set "_no_or_expansion"=false;
set linesize 500
set termout off
alter session set statistics_level=all;
select * from scott.emp where EMPNO=7782 OR ename='FORD';
select * from table(dbms_xplan.display_cursor(null,null,'ADVANCED ALLSTATS LAST PEEKED_BINDS'));
---------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name     | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |          |      1 |        |       |     3 (100)|          |      2 |00:00:00.01 |       4 |
|   1 |  TABLE ACCESS BY INDEX ROWID     | EMP      |      1 |      2 |    76 |     3   (0)| 00:00:01 |      2 |00:00:00.01 |       4 |
|   2 |   BITMAP CONVERSION TO ROWIDS    |          |      1 |        |       |            |          |      2 |00:00:00.01 |       2 |
|   3 |    BITMAP OR                     |          |      1 |        |       |            |          |      1 |00:00:00.01 |       2 |
|   4 |     BITMAP CONVERSION FROM ROWIDS|          |      1 |        |       |            |          |      1 |00:00:00.01 |       1 |
|*  5 |      INDEX RANGE SCAN            | PK_EMP   |      1 |        |       |     0   (0)|          |      1 |00:00:00.01 |       1 |
|   6 |     BITMAP CONVERSION FROM ROWIDS|          |      1 |        |       |            |          |      1 |00:00:00.01 |       1 |
|*  7 |      INDEX RANGE SCAN            | NAME_IND |      1 |        |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       1 |
---------------------------------------------------------------------------------------------------------------------------------------

沒啥子區別,可以說明這個引數到了Oracle 11.2.0.4 版本已經被廢棄了,引數沒有起到效果!!!

2.3 追溯為什麼要設定這個引數?

--客戶歷史老的DBA不可能無緣無故調整隱含引數,一般是出現了問題,隨後的DB都統一調整!
那麼與這個引數相關的問題,有哪些? 請閱讀如下MOS擷取的資訊 如果出現ORA-932 並且符合這個版本,可以考慮重點關注一下!!!
Bug 9592003 : ALL_SDO_GEOM_METADATA QUERIES RESULTS IN ORA-00932 UDT GOT MDSYS.SDO_DIM_ARRAY Product Version 10.2.0.4 Bug 9592003 - ORA-932 error on query with join on UNION ALL view (Doc ID 9592003.8) Oracle Database - Enterprise Edition - Version 10.1.0.2 and later Description ORA-932 error on query with join on union view. Rediscovery Notes: If a query with a join on a union view gets ORA-932 error and disabling or-Expansion allows the query to execute then you may have encountered this bug. This can have a major impact in Oracle Spatial Systems as it was discovered in a very common recursive query against the core ALL_SDO_GEOM_METADATA view. Workaround Use NO_EXPAND hint or set "_no_or_expansion" to TRUE. Bug 12642813 : WRONG RESULT WITH OR-EXPANSION CAUSED BY FIX TO BUG 399198 Hdr: 12642813 11.2.0.2 RDBMS 11.2.0.2 QRY OPTIMIZER PRODID-5 PORTID-23 Abstract: WRONG RESULT WITH OR-EXPANSION CAUSED BY FIX TO BUG 399198 Product Version 11.2.0.2 Fixed in Product Version 12.1 Platform 23 - Oracle Solaris on SPARC (64-bit)

客戶新的機器DB版本11.2.0.4,結論是可以不設定這個引數,如果DB <=11.2.0.2的情況下,如果有補丁也行,否則這個引數設定可以不用取消,放著就行!