日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[20181220]使用提示OR_EXPAND优化.txt

發布時間:2025/4/5 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [20181220]使用提示OR_EXPAND优化.txt 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

[20181220]使用提示OR_EXPAND優化.txt

--//鏈接http://www.itpub.net/thread-2107240-2-1.html,http://www.itpub.net/thread-2107231-2-1.html的討論.
--//ZALBB建議在18c下嘗試看看,我們這里僅僅1臺18c,而且還是生產系統,正好前幾天在辦公機器重新安裝12c,在12c測試看看.
--//主要問題感覺oracle對于這樣的sql有點奇怪....

1.環境:
SCOTT@test01p> @ ver1
PORT_STRING??????????????????? VERSION??????? BANNER?????????????????????????????????????????????????????????????????????????????? CON_ID
------------------------------ -------------- -------------------------------------------------------------------------------- ----------
IBMPC/WIN_NT64-9.1.0?????????? 12.2.0.1.0???? Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production????????????? 0

create table t1 as select rownum id1 ,rownum id2 ,lpad('x',100,'x') name from dual connect by level<=6000;
create table t2 as select rownum id1 ,rownum id2 ,lpad('x',100,'x') name from dual connect by level<=6000;
create index i_t1_id1 on t1(id1);
create index i_t1_id2 on t1(id2);
create index i_t2_id1 on t2(id1);

--//分析略.

2.測試:
SCOTT@test01p> alter session set statistics_level = all;
Session altered.

SCOTT@test01p> select? * from t1 where t1.id1 in? (select? t2.id1 from t2 where t2.id1=11 ) or? (t1.id2=10 );
?????? ID1??????? ID2 NAME
---------- ---------- ----------------------------------------------------------------------------------------------------
??????? 10???????? 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
??????? 11???????? 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

SCOTT@test01p> @ dpc '' ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID? gz5pqkg6svm7k, child number 0
-------------------------------------
select? * from t1 where t1.id1 in? (select? t2.id1 from t2 where
t2.id1=11 ) or? (t1.id2=10 )
Plan hash value: 1962644737
-------------------------------------------------------------------------------------------------------------------------
| Id? | Operation????????? | Name???? | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time?? | A-Rows |?? A-Time?? | Buffers |
-------------------------------------------------------------------------------------------------------------------------
|?? 0 | SELECT STATEMENT?? |????????? |????? 1 |??????? |?????? |??? 30 (100)|????????? |????? 2 |00:00:00.01 |???? 115 |
|*? 1 |? FILTER??????????? |????????? |????? 1 |??????? |?????? |??????????? |????????? |????? 2 |00:00:00.01 |???? 115 |
|?? 2 |?? TABLE ACCESS FULL| T1?????? |????? 1 |?? 6000 |?? 638K|??? 30?? (0)| 00:00:01 |?? 6000 |00:00:00.01 |???? 113 |
|*? 3 |?? FILTER?????????? |????????? |?? 5999 |??????? |?????? |??????????? |????????? |????? 1 |00:00:00.01 |?????? 2 |
|*? 4 |??? INDEX RANGE SCAN| I_T2_ID1 |????? 1 |????? 1 |???? 4 |???? 1?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 2 |
-------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
?? 1 - SEL$1
?? 2 - SEL$1 / T1@SEL$1
?? 3 - SEL$2
?? 4 - SEL$2 / T2@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
?? 1 - filter(("T1"."ID2"=10 OR? IS NOT NULL))
?? 3 - filter(11=:B1)
?? 4 - access("T2"."ID1"=:B1)
32 rows selected.

--//執行計劃存在1個全表掃描.里面的索引選擇性很好,oracle并沒有選擇合理的執行計劃.
--//而且有1個小小的細節,id=4的starts=1,而前面的id=3的starts=5999.你可以看出這里oracle顯示執行計劃有1個小小的bug.
--//id=4的starts應該是5999.這樣看到的邏輯讀不應該是后面的2而是2*5999 = 11998.
--//而且你可以看出oracle忽略的id=4多次INDEX RANGE SCAN的成本.
--//鏈接http://www.itpub.net/thread-2107240-2-1.html里面的顯示倒是正確的.它的版本是11.2.0.4.180717.

3.是否通過提示優化sql語句:
--//首先想到的是USE_CONCAT.
select /*+ USE_CONCAT(@"SEL$1" 8 OR_PREDICATES(1)) */ * from t1 where t1.id1 in? (select /*+unnest */ t2.id1 from t2 where t2.id1=11 ) or? (t1.id2=10 );

--//執行計劃如下:
-------------------------------------------------------------------------------------------------------------------------------------------
| Id? | Operation??????????????????????????? | Name???? | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time?? | A-Rows |?? A-Time?? | Buffers |
-------------------------------------------------------------------------------------------------------------------------------------------
|?? 0 | SELECT STATEMENT???????????????????? |????????? |????? 1 |??????? |?????? |??? 33 (100)|????????? |????? 2 |00:00:00.01 |???? 118 |
|?? 1 |? CONCATENATION?????????????????????? |????????? |????? 1 |??????? |?????? |??????????? |????????? |????? 2 |00:00:00.01 |???? 118 |
|?? 2 |?? TABLE ACCESS BY INDEX ROWID BATCHED| T1?????? |????? 1 |????? 1 |?? 109 |???? 2?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 4 |
|*? 3 |??? INDEX RANGE SCAN????????????????? | I_T1_ID2 |????? 1 |????? 1 |?????? |???? 1?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 3 |
|*? 4 |?? FILTER???????????????????????????? |????????? |????? 1 |??????? |?????? |??????????? |????????? |????? 1 |00:00:00.01 |???? 114 |
|*? 5 |??? TABLE ACCESS FULL???????????????? | T1?????? |????? 1 |?? 5999 |?? 638K|??? 30?? (0)| 00:00:01 |?? 5999 |00:00:00.01 |???? 112 |
|*? 6 |??? FILTER??????????????????????????? |????????? |?? 5999 |??????? |?????? |??????????? |????????? |????? 1 |00:00:00.01 |?????? 2 |
|*? 7 |???? INDEX RANGE SCAN???????????????? | I_T2_ID1 |????? 1 |????? 1 |???? 4 |???? 1?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 2 |
-------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
?? 1 - SEL$1
?? 2 - SEL$1_1 / T1@SEL$1
?? 3 - SEL$1_1 / T1@SEL$1
?? 5 - SEL$1_2 / T1@SEL$1_2
?? 6 - SEL$2
?? 7 - SEL$2?? / T2@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
?? 3 - access("T1"."ID2"=10)
?? 4 - filter( IS NOT NULL)
?? 5 - filter(LNNVL("T1"."ID2"=10))
?? 6 - filter(11=:B1)
?? 7 - access("T2"."ID1"=:B1)

--//很奇怪id=4,依舊選擇過濾,unnest提示沒有用.實際上使用USE_CONCAT相當每個or分支加入LNNVL(條件)來排他符合條件的記錄.
--//也就是oracle依舊選擇的執行計劃不是很理想,甚至比前面還要差.

4.嘗試OR_EXPAND提示:
select /*+ OR_EXPAND */ * from t1 where t1.id1 in? (select? /*+ unnest */ t2.id1 from t2 where t2.id1=11 ) or? (t1.id2=10 );

--//執行計劃如下:
Plan hash value: 1716482303
----------------------------------------------------------------------------------------------------------------------------------------------------
| Id? | Operation????????????????????????????? | Name??????????? | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time?? | A-Rows |?? A-Time?? | Buffers |
----------------------------------------------------------------------------------------------------------------------------------------------------
|?? 0 | SELECT STATEMENT?????????????????????? |???????????????? |????? 1 |??????? |?????? |???? 5 (100)|????????? |????? 2 |00:00:00.01 |?????? 9 |
|?? 1 |? VIEW????????????????????????????????? | VW_ORE_BA8ECEFB |????? 1 |????? 2 |?? 156 |???? 5?? (0)| 00:00:01 |????? 2 |00:00:00.01 |?????? 9 |
|?? 2 |?? UNION-ALL??????????????????????????? |???????????????? |????? 1 |??????? |?????? |??????????? |????????? |????? 2 |00:00:00.01 |?????? 9 |
|?? 3 |??? TABLE ACCESS BY INDEX ROWID BATCHED | T1????????????? |????? 1 |????? 1 |?? 109 |???? 2?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 4 |
|*? 4 |???? INDEX RANGE SCAN?????????????????? | I_T1_ID2??????? |????? 1 |????? 1 |?????? |???? 1?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 3 |
|?? 5 |??? NESTED LOOPS SEMI?????????????????? |???????????????? |????? 1 |????? 1 |?? 113 |???? 3?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 5 |
|*? 6 |???? TABLE ACCESS BY INDEX ROWID BATCHED| T1????????????? |????? 1 |????? 1 |?? 109 |???? 2?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 3 |
|*? 7 |????? INDEX RANGE SCAN????????????????? | I_T1_ID1??????? |????? 1 |????? 1 |?????? |???? 1?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 2 |
|*? 8 |???? INDEX RANGE SCAN?????????????????? | I_T2_ID1??????? |????? 1 |????? 1 |???? 4 |???? 1?? (0)| 00:00:01 |????? 1 |00:00:00.01 |?????? 2 |
----------------------------------------------------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
?? 1 - SET$9162BF3C?? / VW_ORE_BA8ECEFB@SEL$BA8ECEFB
?? 2 - SET$9162BF3C
?? 3 - SET$9162BF3C_1 / T1@SEL$1
?? 4 - SET$9162BF3C_1 / T1@SEL$1
?? 5 - SEL$C90BA1D5
?? 6 - SEL$C90BA1D5?? / T1@SEL$1
?? 7 - SEL$C90BA1D5?? / T1@SEL$1
?? 8 - SEL$C90BA1D5?? / T2@SEL$2
Outline Data
-------------
? /*+
????? BEGIN_OUTLINE_DATA
????? IGNORE_OPTIM_EMBEDDED_HINTS
????? OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
????? DB_VERSION('12.2.0.1')
????? ALL_ROWS
????? OUTLINE_LEAF(@"SEL$C90BA1D5")
????? UNNEST(@"SEL$2")
????? OUTLINE_LEAF(@"SET$9162BF3C_1")
????? OUTLINE_LEAF(@"SET$9162BF3C")
????? OR_EXPAND(@"SEL$1" (1) (2))
????? OUTLINE_LEAF(@"SEL$BA8ECEFB")
????? OUTLINE(@"SET$9162BF3C_2")
????? OUTLINE(@"SEL$2")
????? OUTLINE(@"SET$9162BF3C")
????? OR_EXPAND(@"SEL$1" (1) (2))
????? OUTLINE(@"SEL$1")
????? NO_ACCESS(@"SEL$BA8ECEFB" "VW_ORE_BA8ECEFB"@"SEL$BA8ECEFB")
????? INDEX_RS_ASC(@"SET$9162BF3C_1" "T1"@"SEL$1" ("T1"."ID2"))
????? BATCH_TABLE_ACCESS_BY_ROWID(@"SET$9162BF3C_1" "T1"@"SEL$1")
????? INDEX_RS_ASC(@"SEL$C90BA1D5" "T1"@"SEL$1" ("T1"."ID1"))
????? BATCH_TABLE_ACCESS_BY_ROWID(@"SEL$C90BA1D5" "T1"@"SEL$1")
????? INDEX(@"SEL$C90BA1D5" "T2"@"SEL$2" ("T2"."ID1"))
????? LEADING(@"SEL$C90BA1D5" "T1"@"SEL$1" "T2"@"SEL$2")
????? USE_NL(@"SEL$C90BA1D5" "T2"@"SEL$2")
????? END_OUTLINE_DATA
? */
Predicate Information (identified by operation id):
---------------------------------------------------
?? 4 - access("T1"."ID2"=10)
?? 6 - filter(LNNVL("T1"."ID2"=10))
?? 7 - access("T1"."ID1"=11)
?? 8 - access("T2"."ID1"=11)
?????? filter("T1"."ID1"="T2"."ID1")

--//12c下oracle選擇正確的執行計劃.可以發現id=2使用UNION-ALL,也就是oracle做了查詢轉換成union all的形式.
--//另外我曾經嘗試將ounline date的提示信息加入到11g環境,執行計劃依舊沒有選擇OR_EXPAND.
--//通過10053事件看看.

SCOTT@test01p> @ 10053x cg5kmfhgczjfd 0
PL/SQL procedure successfully completed.

ORE: after OR Expansion:******* UNPARSED QUERY IS *******
SELECT "VW_ORE_BA8ECEFB"."ITEM_1" "ID1","VW_ORE_BA8ECEFB"."ITEM_2" "ID2","VW_ORE_BA8ECEFB"."ITEM_3" "NAME" FROM? ( (SELECT "T1"."ID1" "ITEM_1","T1"."ID2" "ITEM_2","T1"."NAME" "ITEM_3" FROM "SCOTT"."T1" "T1" WHERE "T1"."ID2"=10) UNION ALL? (SELECT "T1"."ID1" "ITEM_1","T1"."ID2" "ITEM_2","T1"."NAME" "ITEM_3" FROM "SCOTT"."T1" "T1" WHERE "T1"."ID1"=ANY (SELECT /*+ UNNEST */ "T2"."ID1" "ID1" FROM "SCOTT"."T2" "T2" WHERE "T2"."ID1"=11) AND LNNVL("T1"."ID2"=10))) "VW_ORE_BA8ECEFB"

--//格式化顯示如下:
SELECT "VW_ORE_BA8ECEFB"."ITEM_1" "ID1"
????? ,"VW_ORE_BA8ECEFB"."ITEM_2" "ID2"
????? ,"VW_ORE_BA8ECEFB"."ITEM_3" "NAME"
? FROM ( (SELECT "T1"."ID1" "ITEM_1"
??????????????? ,"T1"."ID2" "ITEM_2"
??????????????? ,"T1"."NAME" "ITEM_3"
??????????? FROM "SCOTT"."T1" "T1"
?????????? WHERE "T1"."ID2" = 10)
??????? UNION ALL
??????? (SELECT "T1"."ID1" "ITEM_1"
?????????????? ,"T1"."ID2" "ITEM_2"
?????????????? ,"T1"."NAME" "ITEM_3"
?????????? FROM "SCOTT"."T1" "T1"
????????? WHERE???? "T1"."ID1" = ANY (SELECT /*+ UNNEST */
??????????????????????????????????????????? "T2"."ID1" "ID1"
??????????????????????????????????????? FROM "SCOTT"."T2" "T2"
?????????????????????????????????????? WHERE "T2"."ID1" = 11)
??????????????? AND LNNVL ("T1"."ID2" = 10))) "VW_ORE_BA8ECEFB";

--//也就是oracle查詢轉換為 UNION ALL的形式.
--//你可以看到第2個條件人為的加入LNNVL ("T1"."ID2" = 10).
--// OR_EXPAND 提示 與 USE_CONCAT 提示到底有什么不同?

5.補充使用USE_CONCAT看到的情況:

select /*+ USE_CONCAT(@"SEL$1" 8 OR_PREDICATES(1)) */ * from t1 where t1.id1 in? (select /*+unnest */ t2.id1 from t2 where t2.id1=11 ) or? (t1.id2=10 );

SCOTT@test01p> @ 10053x 18h6hkqcqq3w2 0
PL/SQL procedure successfully completed.

--//看這些太煩,不過可以發現如下:
LORE: Or-Expansion validity checks failed on query block SEL$2 (#2) because Cost based OR expansion enabled

SYS@test01p> @ hide or_exp
old? 10:? and lower(a.ksppinm) like lower('%&1%')
new? 10:? and lower(a.ksppinm) like lower('%or_exp%')
NAME?????????????????????????????? DESCRIPTION?????????????????????????????????????? DEFAULT_VALUE SESSION_VALUE SYSTEM_VALUE
---------------------------------- ------------------------------------------------- ------------- ------------- ------------
_no_or_expansion?????????????????? OR expansion during optimization disabled???????? TRUE????????? FALSE???????? FALSE
_optimizer_cbqt_or_expansion?????? enables cost based OR expansion?????????????????? TRUE????????? ON??????????? ON
_optimizer_interleave_or_expansion interleave OR Expansion during CBQT?????????????? TRUE????????? TRUE????????? TRUE
_optimizer_or_expansion??????????? control or expansion approach used??????????????? TRUE????????? DEPTH???????? DEPTH
_optimizer_or_expansion_subheap??? Use subheap for optimizer or-expansion??????????? TRUE????????? TRUE????????? TRUE
_or_expand_nvl_predicate?????????? enable OR expanded plan for NVL/DECODE predicate? TRUE????????? TRUE????????? TRUE
6 rows selected.
--//也就是12c缺省打開因為以上原因.不過我嘗試"_optimizer_cbqt_or_expansion"=off也無效.放棄!!

--//我也嘗試提高全表掃描的成本看看是否執行計劃會發生改變,不過依舊沒用.
SCOTT@test01p> exec dbms_stats.SET_TABLE_STATS(user,'T1',NUMBLKS=>800000000000);
PL/SQL procedure successfully completed.

轉載于:https://www.cnblogs.com/lfree/p/10150079.html

總結

以上是生活随笔為你收集整理的[20181220]使用提示OR_EXPAND优化.txt的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。