繫結變數,組合查詢方式,導致CBO錯誤一例
生產系統,出現一個SQL,執行計劃不對,SQL如下:
SELECT SDMFID GMFMFID,
'[' || TO_CHAR(TO_NUMBER(PMCODE)) || ']' || PMNAME NAME,
SUM(SPGGDMONEY * FGETINVSIGN(SHDJLB)) JE
FROM SELLHEAD, SELLDETAIL, SELLPAYGOODS, PAYMODE, GOODSMFRAME
WHERE SHBILLNO = SPGBILLNO
AND SHBILLNO = SDBILLNO
AND SDROWNO = SPGGDROW
AND SPGPMCODE = PMCODE
AND SDMFID = GMFMFID
AND SDGDID = GMFGDID
AND GMFMARKET = :as_mkt
AND SPGPMCODE <> '0500'
AND PMTYPE = '5'
AND (GMFMFID = :as_mf OR NVL(:as_mf, '#') = '#')
AND SHDATE >= TRUNC(to_date(:adt_start,'YYYY-MM-DD'))
AND SHDATE < TRUNC(to_date(:adt_end,'YYYY-MM-DD')) + 1
GROUP BY SDMFID, PMCODE, PMNAME
這裡要注意的是,:as_mf 變數傳遞進來的值是空''。可以看到,採用了繫結變數的方式。執行計劃如下:
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Inst |IN-OUT|
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1265 (100)| | | |
| 1 | HASH GROUP BY | | 1 | 150 | 1265 (1)| 00:00:16 | | |
|* 2 | FILTER | | | | | | | |
|* 3 | TABLE ACCESS BY INDEX ROWID| SELLPAYGOODS | 1 | 34 | 3 (0)| 00:00:01 | | |
| 4 | NESTED LOOPS | | 1 | 150 | 1264 (1)| 00:00:16 | | |
|* 5 | HASH JOIN | | 1 | 116 | 1261 (1)| 00:00:16 | | |
| 6 | REMOTE | SELLHEAD | 1101 | 27525 | 29 (0)| 00:00:01 | POS_DB | R->S |
| 7 | NESTED LOOPS | | 2160 | 191K| 1238 (1)| 00:00:15 | | |
| 8 | MERGE JOIN CARTESIAN | | 122 | 5490 | 322 (1)| 00:00:04 | | |
|* 9 | TABLE ACCESS FULL | PAYMODE | 1 | 20 | 3 (0)| 00:00:01 | | |
| 10 | BUFFER SORT | | 166 | 4150 | 319 (1)| 00:00:04 | | |
|* 11 | TABLE ACCESS FULL | GOODSMFRAME | 166 | 4150 | 319 (1)| 00:00:04 | | |
| 12 | REMOTE | SELLDETAIL | 18 | 828 | 46 (0)| 00:00:01 | POS_DB | R->S |
|* 13 | INDEX RANGE SCAN | PK_SELLPAYGOODS | 1 | | 2 (0)| 00:00:01 | | |
-----------------------------------------------------------------------------------------------------------------
這個執行計劃的主要問題是粗黑體顯示的NEST LOOP,而導致這裡選擇nest loop的主要原因是MERGE JOIN CARTESIAN 完畢後,Card只有122
看看實際的值:
SQL> SELECT count(*)
2 FROM PAYMODE, GOODSMFRAME
3 WHERE GMFMARKET = '5101'
4 AND PMTYPE = 5
5 AND (GMFMFID = '' OR NVL('', '#') = '#');
COUNT(*)
----------
93058
由於使用了變數,導致(GMFMFID = '' OR NVL('', '#') = '#')的選擇度判斷不正確,並且,即使進行了變數窺視,也依然如此。
解決的方式是,這裡不要進行變數繫結。
SELECT SDMFID GMFMFID,
'[' || TO_CHAR(TO_NUMBER(PMCODE)) || ']' || PMNAME NAME,
SUM(SPGGDMONEY * FGETINVSIGN(SHDJLB)) JE
FROM SELLHEAD, SELLDETAIL, SELLPAYGOODS, PAYMODE, GOODSMFRAME
WHERE SHBILLNO = SPGBILLNO
AND SHBILLNO = SDBILLNO
AND SDROWNO = SPGGDROW
AND SPGPMCODE = PMCODE
AND SDMFID = GMFMFID
AND SDGDID = GMFGDID
AND GMFMARKET = :as_mkt
AND SPGPMCODE <> '0500'
AND PMTYPE = 5
AND (GMFMFID = '' OR NVL('', '#') = '#')
AND SHDATE >= TRUNC(:adt_start)
AND SHDATE < TRUNC(:adt_end) + 1
GROUP BY SDMFID, PMCODE, PMNAME
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Inst |IN-OUT|
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 150 | 3583 | | |
| 1 | HASH GROUP BY | | 1 | 150 | 3583 | | |
| 2 | FILTER | | | | | | |
| 3 | NESTED LOOPS | | 1 | 150 | 3582 | | |
| 4 | NESTED LOOPS | | 3 | 375 | 3576 | | |
| 5 | NESTED LOOPS | | 43 | 3397 | 3493 | | |
| 6 | HASH JOIN | | 4283 | 246K| 3492 | | |
| 7 | REMOTE | SELLHEAD | 4212 | 102K| 182 | POS_DB | R->S |
| 8 | TABLE ACCESS FULL | SELLPAYGOODS | 89123 | 2959K| 3309 | | |
| 9 | TABLE ACCESS BY INDEX ROWID| PAYMODE | 1 | 20 |1 | | |
| 10 | INDEX UNIQUE SCAN | PK_PAYMODE | 1 | |0 | | |
| 11 | REMOTE | SELLDETAIL | 1 | 46 |2 | POS_DB | R->S |
| 12 | TABLE ACCESS BY INDEX ROWID | GOODSMFRAME | 1 | 25 |2 | | |
| 13 | INDEX UNIQUE SCAN | PK_GOODSMFRAME | 1 | |1 | | |
---------------------------------------------------------------------------------------------------
資料庫版本:10.2.0.1
[@more@]來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/19423/viewspace-1056079/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- V$sql查詢未使用繫結變數的語句SQL變數
- Oracle資料傾斜導致的問題-無繫結變數Oracle變數
- Oracle資料傾斜導致的問題-有繫結變數Oracle變數
- [20210112]完善查詢繫結變數指令碼bind_cap.txt變數指令碼
- Oracle中如何查詢未使用繫結變數的SQL語句?Oracle變數SQL
- 連結伺服器查詢導致的阻塞伺服器
- C++編譯錯誤的正確查詢方式C++編譯
- mysql-分組查詢-子查詢-連線查詢-組合查詢MySql
- 組合查詢(UNION)
- 日誌查詢錯誤
- Session物件改變請求頭值導致的401錯誤Session物件
- SpringBoot分頁查詢 頁碼問題導致返回結果數量為0Spring Boot
- delphi 查詢av錯誤地址
- MySQL全面瓦解11:子查詢和組合查詢MySql
- Oracle分組查詢中包含子查詢列,發生ORA-00937:不是單分組函式的錯誤Oracle函式
- Win7 .lnk快捷方式被繫結到以wps開啟導致所有快捷方式失效Win7
- MySQL--操作簡記(聯結表,組合查詢(UNION))MySql
- SQL 兩個表組合查詢SQL
- 透過手機號查詢繫結QQ
- Vue select 繫結動態變數Vue變數
- 在繫結變數下使用outline變數
- MySQL高階特性——繫結變數MySql變數
- [20180930]in list與繫結變數.txt變數
- [20180912]PLSLQ與繫結變數.txt變數
- NKMySQL 查詢樹結構方式gllMySql
- Lombok 的@ToString導致的Maven編譯錯誤LombokMaven編譯
- ORA-04031錯誤導致當機案例分析
- git合併丟失程式碼問題分析與解決(錯誤操作導致)Git
- MySQL入門系列:查詢簡介(七)之組合查詢MySql
- MySQL查詢結果匯出方式總結MySql
- [20210120]in list與繫結變數個數.txt變數
- [20180930]in list與繫結變數個數.txt變數
- mybatis lambdaQuery 查詢條件導致空指標MyBatis指標
- [20181130]hash衝突導致查詢緩慢.txt
- async 與 Thread 的錯誤結合thread
- 通過這次聯合 (union) 查詢瞭解 Laravel DB 的資料繫結Laravel
- [BUG反饋]文件頁面聯合查詢時有個錯誤,求解決?
- 17. 使用MySQL之組合查詢MySql
- 聊聊mysql的多列組合查詢MySql