一次ORACLE SQL謂詞跨界導致的執行計劃不準
一次ORACLE SQL謂詞跨界導致的執行計劃不準
首先說明謂詞跨界一般出現在日期型別中,打個比方你的統計資料是8月20號的,但是今天是8月28日,在這20號到28號之間日期是沒有進入統計資料的,
這樣可能導致,根據統計資訊計算出來的COST異常的小,這樣可能導致本來該走其他欄位索引的語句走到時間索引上去,導致執行計劃最終錯誤。
在10053中可以看到如下提示:
as selectvity of out-of-range/non-existent value pred
以前多次遇到過,今天再次遇到,就記錄於此,如下SQL
select *
from test
where seller_user_id = '123'
and raw_add_time >= trunc(sysdate-1, 'mi')
and raw_add_time < trunc(sysdate, 'mi')
其執行計算如下:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2023568823
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 574 |
|* 1 | FILTER | | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 574 |
|* 3 | INDEX RANGE SCAN | TEST_ADD_TIME_INDEX | 2 | |
--------------------------------------------------------------------------------
這裡test_ADD_TIME_INDEX就是我的時間上的索引,透過檢視選擇率後發現seller_user_id遠遠
小於raw_add_time範圍的選擇率,應該走到seller_user_id上的索引才對,這裡可能發生了
謂詞跨界檢視其統計資料發現是7月20號的,今天是8月28日。然後進行了一下驗證
調整時間後
select *
from test
where seller_user_id = '123'
and raw_add_time >= trunc(sysdate-100, 'mi')
and raw_add_time < trunc(sysdate-99, 'mi')
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 576270446
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cos
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 574 |
|* 1 | FILTER | | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| TEST_BASE_INFO | 1 | 574 |
|* 3 | INDEX RANGE SCAN | TEST_ID_INDEX | 23 | |
--------------------------------------------------------------------------------
這裡更改了時間範圍在已知的統計資料範圍內,執行計劃正確。
我們進行10053 TRACE驗證:
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for TEST[TEST]
Column (#14):
NewDensity:0.000001, OldDensity:0.000623 BktCnt:254, PopBktCnt:79, PopValCnt:7, NDV:814912
Column (#14): SELLER_USER_ID(
AvgLen: 21 NDV: 814912 Nulls: 855565 Density: 0.000001
Histogram: HtBal #Bkts: 254 UncompBkts: 254 EndPtVals: 183
Column (#41): RAW_ADD_TIME(
AvgLen: 8 NDV: 13533184 Nulls: 0 Density: 0.000000 Min: 2454768 Max: 2457225
Using prorated density: 0.000000 of col #41 as selectvity of out-of-range/non-existent value pred //謂詞跨界
Table: TEST Alias: TEST
Card: Original: 27510606.000000 Rounded: 1 Computed: 0.00 Non Adjusted: 0.00
Access Path: TableScan
Cost: 618899.27 Resp: 618899.27 Degree: 0
Cost_io: 616819.00 Cost_cpu: 43729541941
Resp_io: 616819.00 Resp_cpu: 43729541941
Using prorated density: 0.000000 of col #41 as selectvity of out-of-range/non-existent value pred //謂詞跨界
Access Path: index (RangeScan)
Index: TEST_ADD_TIME_INDEX
resc_io: 5.00 resc_cpu: 39819
ix_sel: 0.000000 ix_sel_with_filters: 0.000000
Cost: 5.00 Resp: 5.00 Degree: 1
謂詞跨界後選擇率成為了0.000000,這樣導致了執行計劃錯誤。
解決也很簡單,按需求重新收集統計資訊即可
首先說明謂詞跨界一般出現在日期型別中,打個比方你的統計資料是8月20號的,但是今天是8月28日,在這20號到28號之間日期是沒有進入統計資料的,
這樣可能導致,根據統計資訊計算出來的COST異常的小,這樣可能導致本來該走其他欄位索引的語句走到時間索引上去,導致執行計劃最終錯誤。
在10053中可以看到如下提示:
as selectvity of out-of-range/non-existent value pred
以前多次遇到過,今天再次遇到,就記錄於此,如下SQL
select *
from test
where seller_user_id = '123'
and raw_add_time >= trunc(sysdate-1, 'mi')
and raw_add_time < trunc(sysdate, 'mi')
其執行計算如下:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2023568823
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 574 |
|* 1 | FILTER | | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 574 |
|* 3 | INDEX RANGE SCAN | TEST_ADD_TIME_INDEX | 2 | |
--------------------------------------------------------------------------------
這裡test_ADD_TIME_INDEX就是我的時間上的索引,透過檢視選擇率後發現seller_user_id遠遠
小於raw_add_time範圍的選擇率,應該走到seller_user_id上的索引才對,這裡可能發生了
謂詞跨界檢視其統計資料發現是7月20號的,今天是8月28日。然後進行了一下驗證
調整時間後
select *
from test
where seller_user_id = '123'
and raw_add_time >= trunc(sysdate-100, 'mi')
and raw_add_time < trunc(sysdate-99, 'mi')
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 576270446
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cos
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 574 |
|* 1 | FILTER | | | |
|* 2 | TABLE ACCESS BY INDEX ROWID| TEST_BASE_INFO | 1 | 574 |
|* 3 | INDEX RANGE SCAN | TEST_ID_INDEX | 23 | |
--------------------------------------------------------------------------------
這裡更改了時間範圍在已知的統計資料範圍內,執行計劃正確。
我們進行10053 TRACE驗證:
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for TEST[TEST]
Column (#14):
NewDensity:0.000001, OldDensity:0.000623 BktCnt:254, PopBktCnt:79, PopValCnt:7, NDV:814912
Column (#14): SELLER_USER_ID(
AvgLen: 21 NDV: 814912 Nulls: 855565 Density: 0.000001
Histogram: HtBal #Bkts: 254 UncompBkts: 254 EndPtVals: 183
Column (#41): RAW_ADD_TIME(
AvgLen: 8 NDV: 13533184 Nulls: 0 Density: 0.000000 Min: 2454768 Max: 2457225
Using prorated density: 0.000000 of col #41 as selectvity of out-of-range/non-existent value pred //謂詞跨界
Table: TEST Alias: TEST
Card: Original: 27510606.000000 Rounded: 1 Computed: 0.00 Non Adjusted: 0.00
Access Path: TableScan
Cost: 618899.27 Resp: 618899.27 Degree: 0
Cost_io: 616819.00 Cost_cpu: 43729541941
Resp_io: 616819.00 Resp_cpu: 43729541941
Using prorated density: 0.000000 of col #41 as selectvity of out-of-range/non-existent value pred //謂詞跨界
Access Path: index (RangeScan)
Index: TEST_ADD_TIME_INDEX
resc_io: 5.00 resc_cpu: 39819
ix_sel: 0.000000 ix_sel_with_filters: 0.000000
Cost: 5.00 Resp: 5.00 Degree: 1
謂詞跨界後選擇率成為了0.000000,這樣導致了執行計劃錯誤。
解決也很簡單,按需求重新收集統計資訊即可
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-1785103/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ORACLE analyse table方式收集表統計資訊導致SQL執行計劃不準確而效能下降OracleSQL
- 統計資訊不準確導致執行計劃走了笛卡爾積
- sql中使用函式導致explain plan for和set autotrace得到執行計劃不準確SQL函式AI
- Oracle sql執行計劃OracleSQL
- 執行計劃-4:謂詞的選擇時機與使用細節
- 執行計劃的偏差導致的效能問題
- Oracle中檢視已執行sql的執行計劃OracleSQL
- Oracle 檢視SQL的執行計劃OracleSQL
- 完美的執行計劃導致的效能問題
- SQL 改寫系列六:謂詞推導SQL
- set autotrace on 產生不準確的執行計劃
- Grant許可權導致執行計劃失效
- Oracle SQL Profile固定執行計劃的方法OracleSQL
- oracle中跟蹤sql執行計劃的方法OracleSQL
- SQL的執行計劃SQL
- Oracle 獲取SQL執行計劃方法OracleSQL
- Oracle手動固定SQL執行計劃OracleSQL
- 找出導致db file scattered read等待事件發生的SQL及其執行計劃事件SQL
- Oracle檢視正在執行的SQL以及執行計劃分析OracleSQL
- sql 執行計劃SQL
- date列統計資訊陳舊導致sql沒有選擇最優執行計劃SQL
- 統計資訊不正確導致執行計劃的錯誤選擇
- autotrace 和explain plan for可能導致執行計劃錯誤AI
- 執行計劃錯誤導致系統負載高負載
- 為什麼該SQL的執行計劃不走索引???SQL索引
- 執行SQL語句導致mysqld的crashMySql
- 如何在oracle10g上檢視sql的執行計劃(不實際執行語句)OracleSQL
- 11G的SORT GROUP BY NOSORT導致錯誤執行計劃
- 記一次,因表變數導致SQL執行效率變慢變數SQL
- Oracle資料庫關於SQL的執行計劃Oracle資料庫SQL
- SQL Server執行計劃SQLServer
- SQL執行計劃分析SQL
- 【SQL】Oracle查詢轉換之謂詞推送SQLOracle
- ORACLE執行計劃Oracle
- 【sql調優之執行計劃】獲取執行計劃SQL
- sql的執行計劃 詳解SQL
- 多種方法檢視Oracle SQL執行計劃OracleSQL
- oracle10g 檢視SQL執行計劃OracleSQL