【隱式轉換】注意隱式轉換將導致索引無法使用
在文章《【問題處理】ORA-01722: invalid number》(http://space.itpub.net/519536/viewspace-660522)中描述了一個有關隱式轉換的隱蔽的問題。
本文將展示“隱式轉換”直接帶給我們的弊端——索引無法得到有效地使用。
1.建立測試表T並初始化幾行字串內容
sec@ora10g> create table t (x varchar2(10));
Table created.
sec@ora10g> insert into t values ('1');
1 row created.
sec@ora10g> insert into t values ('2');
1 row created.
sec@ora10g> insert into t values ('3');
1 row created.
sec@ora10g> commit;
Commit complete.
sec@ora10g> select * from t;
X
----------
1
2
3
2.在表T的X欄位建立索引I_T
sec@ora10g> create index i_t on t(x);
Index created.
3.開啟autotrace功能跟蹤SQL語句的執行計劃
sec@ora10g> set autotrace traceonly explain
4.正常情況下,索引可被使用
sec@ora10g> select * from t where x = '1';
Execution Plan
----------------------------------------------------------
Plan hash value: 2616361825
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| I_T | 1 | 7 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("X"='1')
Note
-----
- dynamic sampling used for this statement
5.驗證發生隱式轉化時索引無法被使用
去掉“1”前後的單引號,再次執行上述SQL語句,此時字串型別的X欄位將與一個數字進行匹配,此時會發生隱式轉換。
sec@ora10g> select * from t where x = 1;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 1 | 7 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("X")=1)
Note
-----
- dynamic sampling used for this statement
可見,在隱式轉換髮生的情況下,索引時無法被使用到的。
6.小結
如果在程式開發過程中出現隱式轉換型別的SQL,在生產環境中將是一個較大的隱患。在資料量逐漸增大的系統中該問題將會漸漸的凸顯。
應對策略很簡單,針對具體欄位型別賦予與之相符的值。
Good luck.
secooler
10.04.23
-- The End --
本文將展示“隱式轉換”直接帶給我們的弊端——索引無法得到有效地使用。
1.建立測試表T並初始化幾行字串內容
sec@ora10g> create table t (x varchar2(10));
Table created.
sec@ora10g> insert into t values ('1');
1 row created.
sec@ora10g> insert into t values ('2');
1 row created.
sec@ora10g> insert into t values ('3');
1 row created.
sec@ora10g> commit;
Commit complete.
sec@ora10g> select * from t;
X
----------
1
2
3
2.在表T的X欄位建立索引I_T
sec@ora10g> create index i_t on t(x);
Index created.
3.開啟autotrace功能跟蹤SQL語句的執行計劃
sec@ora10g> set autotrace traceonly explain
4.正常情況下,索引可被使用
sec@ora10g> select * from t where x = '1';
Execution Plan
----------------------------------------------------------
Plan hash value: 2616361825
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| I_T | 1 | 7 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("X"='1')
Note
-----
- dynamic sampling used for this statement
5.驗證發生隱式轉化時索引無法被使用
去掉“1”前後的單引號,再次執行上述SQL語句,此時字串型別的X欄位將與一個數字進行匹配,此時會發生隱式轉換。
sec@ora10g> select * from t where x = 1;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T | 1 | 7 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("X")=1)
Note
-----
- dynamic sampling used for this statement
可見,在隱式轉換髮生的情況下,索引時無法被使用到的。
6.小結
如果在程式開發過程中出現隱式轉換型別的SQL,在生產環境中將是一個較大的隱患。在資料量逐漸增大的系統中該問題將會漸漸的凸顯。
應對策略很簡單,針對具體欄位型別賦予與之相符的值。
Good luck.
secooler
10.04.23
-- The End --
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/519536/viewspace-660638/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle隱式型別轉換導致索引失效Oracle型別索引
- 高效的SQL(隱式轉換導致不走索引)SQL索引
- MySQL索引失效之隱式轉換MySql索引
- js顯式轉換和隱式轉換JS
- 資料型別隱式轉換導致的阻塞資料型別
- javascript 隱式轉換JavaScript
- sql隱式轉換SQL
- Oracle 隱式轉換Oracle
- java隱式轉換Java
- 索引失效系列——隱式型別轉換索引型別
- Scala - 隱式轉換和隱式引數
- Scala隱式轉換與隱式引數
- 索引關鍵字的隱式轉換分析索引
- Scala Essentials: 隱式轉換
- JavaScript隱式型別轉換JavaScript型別
- mysql隱式轉換問題MySql
- MySQL 隱式型別轉換MySql型別
- 【C++】禁止隱式轉換C++
- 相容模式下導致數值型別發生隱式轉換,SQL在生產上無法正常使用案例模式型別SQL
- scala中隱式轉換之隱式轉換呼叫類中本不存在的方法
- Java資料型別的顯式轉換和隱式轉換Java資料型別
- [] == ![],走進==隱式轉換的世界
- JS隱式轉換--寬鬆相等(==)JS
- 筆記:隱式轉換規則筆記
- C# 隱式型別轉換(轉載)C#型別
- 隱形轉換導致全表掃描案例
- oracle資料隱式轉換規則Oracle
- JavaScript 隱式資料型別轉換JavaScript資料型別
- Spark中的三種隱式轉換Spark
- 如何實現隱式型別轉換型別
- 你所忽略的js隱式轉換JS
- MySQL和Oracle中的隱式轉換MySqlOracle
- 談談 MySQL 隱式型別轉換MySql型別
- C++隱式類型別轉換C++型別
- C++隱式型別的轉換C++型別
- C++ 隱式類型別轉換C++型別
- 資料型別的隱式轉換資料型別
- 有趣的JavaScript隱式型別轉換JavaScript型別