SQL hint中正確使用use_nl提示
地址:http://rdc.taobao.com/blog/dba/html/114_oracle_use_nl.html
之前對use_nl的理解一直很模糊,看下面的案例。
2 from table_detail t,
3 table(cast(str2varlist('123') as vartabletype)) t2
4 where t.id = t2.column_value;
Execution Plan
----------------------------------------------------------
Plan hash value: 31598426
----------------------------------------------------------
Operation | Name |Rows |Bytes|Cost(%CPU)|Time|
----------------------------------------------------------
SELECT STATEMENT | |784K|124M|2132(1)|00:00:26|
NESTED LOOPS | |784K|124M|2132(1)|00:00:26|
TABLE ACCESS FULL | table_detail|96 |15744| 11(0)|00:00:01|
COLLECTION ITERATOR PICKLER FETCH| STR2VARLIST | | | | |
-------------------------------------------------------------
t2是個虛擬的表,沒有準確的統計資訊,很容易出現執行計劃錯誤,這種sql最好要用hint來固化其執行計劃。
1.使用/*+ ORDERED use_nl(t2,t) */提示
2 from table_detail t,
3 table(cast(str2varlist('123') as vartabletype)) t2
4 where t.id = t2.column_value;
Execution Plan
----------------------------------------------------------
Plan hash value: 3775534098
----------------------------------------------------------------------------
Operation | Name |Rows |Bytes|Cost(%CPU)|Time|
----------------------------------------------------------------------------
SELECT STATEMENT | |784K|124M|2132(1)|00:00:26|
NESTED LOOPS | |784K|124M|2132(1)|00:00:26|
TABLE ACCESS FULL | table_detail|96 |15744| 11(0)|00:00:01|
COLLECTION ITERATOR PICKLER FETCH| STR2VARLIST | | | | |
----------------------------------------------------------------------------
執行計劃是錯誤的,還是取table_detail為驅動表。
錯誤理解:使用order提示,執行計劃會去取use_nl(t2,t)中的t2作為驅動表。
2.使用/*+ ORDERED use_nl(t,t2) */提示
2 from table_detail t,
3 table(cast(str2varlist('123') as vartabletype)) t2
4 where t.id = t2.column_value;
Execution Plan
----------------------------------------------------------
Plan hash value: 3775534098
----------------------------------------------------------------------------
Operation | Name |Rows |Bytes|Cost(%CPU)|Time|
----------------------------------------------------------------------------
SELECT STATEMENT | |784K|124M|2132(1)|00:00:26|
NESTED LOOPS | |784K|124M|2132(1)|00:00:26|
TABLE ACCESS FULL | table_detail|96 |15744| 11(0)|00:00:01|
COLLECTION ITERATOR PICKLER FETCH| STR2VARLIST | | | | |
----------------------------------------------------------------------------
執行計劃還是錯誤的,這到底是怎麼回事?
3.使用/*+ ORDERED use_nl(t,t2) */提示,同時調整了表順序。
2 from table(cast(str2varlist('123') as vartabletype)) t2,
3 table_detail t
4 where t.id = t2.column_value;
Execution Plan
----------------------------------------------------------
Plan hash value: 2272521841
-------------------------------------------------------------------------------
Operation | Name Rows |Bytes |Cost (%CPU)|Time|
-------------------------------------------------- ----------------------------
SELECT STATEMENT | |784K| 124M|25 (0)|00:00:01|
TABLE ACCESS BY INDEX ROWID | table_detail | 96 |15744| 1 (0)|00:00:01|
NESTED LOOPS | |784K| 124M|25 (0)|00:00:01|
COLLECTION ITERATOR PICKLER FETCH| STR2VARLIST | | | | |
INDEX RANGE SCAN | IND_deail_id | 1 | | 1 (0)|00:00:01|
-------------------------------------------------- ----------------------------
這回執行計劃是正確的,原來order是根據from表順序來決定驅動表,而不是use_nl(t,t2)中表的先後順序。
調整from後面的表順序是很老土的調優,彷彿回到了rbo的年代,採用leading指定驅動表看是否可行。
4.使用leading提示來指定驅動表
2 from table_detail t,
3 table(cast(str2varlist('123') as vartabletype)) t2
4 where t.id = t2.column_value;
Execution Plan
----------------------------------------------------------
Plan hash value: 2272521841
-------------------------------------------------------------------------------
Operation | Name Rows |Bytes |Cost (%CPU)|Time|
-------------------------------------------------- ----------------------------
SELECT STATEMENT | |784K| 124M|25 (0)|00:00:01|
TABLE ACCESS BY INDEX ROWID | table_detail | 96 |15744| 1 (0)|00:00:01|
NESTED LOOPS | |784K| 124M|25 (0)|00:00:01|
COLLECTION ITERATOR PICKLER FETCH| STR2VARLIST | | | | |
INDEX RANGE SCAN | IND_deail_id | 1 | | 1 (0)|00:00:01|
-------------------------------------------------- ----------------------------
1./*+use_nl(t2,t) */ 提示走nest loop,但沒有提示t2還是t為驅動表 。
2./*+ ordered use_nl(t2,t) */提示走nest loop,order提示的是from後面的第一個表為驅動表。
3./*+ leading(t2) use_nl(t) */ 直接提示t2為驅動表。
結論:use_nl不能讓優化器確定誰是驅動表誰是被驅動的表,use_nl(t,t2)也沒有指出哪個是驅動表,這時候我們需要使用ordered,leading來強制指定驅動表,以達到我們的目的。
--EOF--
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10742223/viewspace-235563/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【HINT】使用“NO_INDEX ”Hint提示避免SQL使用特定索引IndexSQL索引
- 【sql hint 提示】SQL
- MySQL SQL hint 提示MySql
- 在Java中正確使用註釋Java
- Oracle 12c 新SQL提示(hint)OracleSQL
- 在Python中正確使用UnicodePythonUnicode
- Sql最佳化(五) hint(提示)介紹SQL
- Oracle Hint:USE_NL、USE_MERGE、UESE_HASH(原理)Oracle
- oracle sql hint提示_BITMAP CONVERSION FROM ROWIDSOracleSQL
- 【SQL 提示 之二】index_ss Index Skip HintSQLIndex
- Android App 中正確地使用 Splash Screen(譯)AndroidAPP
- 如何在 Java 中正確使用 wait, notify 和 notifyAllJavaAI
- 檢視SQL PROFILE使用的HINTSQL
- 【sql調優之執行計劃】使用hint(五)Hint for parallelSQLParallel
- Python 列表表示式中正確使用 dict.updatePython
- 如何在 JS 迴圈中正確使用 async 與 awaitJSAI
- git在工作中正確的使用方式----git rebase篇Git
- sql hint articleSQL
- Oralce SQL hintSQL
- 使用Oracle Hint提示來更改執行計劃Oracle
- 使用hint來調優sql語句SQL
- 使用Oracle Hint提示來更改執行計劃 ZTOracle
- 【DBAplus】SQL優化:一篇文章說清楚Oracle Hint的正確使用姿勢SQL優化Oracle
- 透過使用hint unnest調優sql語句SQL
- 通過使用hint unnest調優sql語句SQL
- Oracle中的sql hintOracleSQL
- Android中正確儲存view的狀態AndroidView
- vue中正確使用富文字編輯器wangeditor和使用wangeditor遇到的坑Vue
- 如何在網頁設計中正確應用色彩?網頁
- openGauss 支援SQL-hintSQL
- 宜信DBA實踐-SQL優化|一篇文章說清楚Oracle Hint的正確使用姿勢SQL優化Oracle
- 抖機靈而不翻車:在網頁設計中正確地使用幽默網頁
- 使用USE_HASH Hint調優一個SQL語句SQL
- Laravel 5.8 中正確地應用 Repository 設計模式Laravel設計模式
- build.gradle中正確地匯入RecyclerView依賴UIGradleView
- 在Windows XP中正確配置CPU二級快取(轉)Windows快取
- 如何在Form中正確使用Ole2訪問Excel,將資料輸入ExcelORMExcel
- 11G new SQL hint大全SQL