https://cloud.tencent.com/developer/article/1873328
隱式轉換(Implicit Conversion)就像他的名字一樣,是個隱秘、不容易被發現的問題,但歸根結底,還是設計開發中未遵守相關的規範,或者說是不良的設計開發習慣所導致的。
如果在條件中的欄位和變數型別不一致,資料庫會按照低精度向高精度的順序進行隱式轉換,轉換的過程就會消耗資源,例如CPU,但是更關鍵的是如果隱式轉換的欄位是索引列,就會導致因使用了函式而不能用到索引,該使用索引掃描的執行計劃就變成了全表掃描,這對系統效能來說就是潛在的風險。
例如在Oracle中,型別轉換如下,
字串型別轉換關係,
測試表test的object_name是varchar2型別,subobject_name是nvarchar2型別,都建立了索引,
SQL> create table test as select * from dba_objects;
Table created.
SQL> select count(*) from test;
COUNT(*)
----------
97095
SQL> create index idx_test_01 on test(object_name);
Index created.
SQL> alter table test modify subobject_name nvarchar2(30);
Table altered.
SQL> create index idx_test_02 on test(subobject_name);
Index created.
SQL> desc test
Name Null? Type
---------------- -------- ----------------------
OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(128)
SUBOBJECT_NAME NVARCHAR2(30)
...
構造where varchar2=nvarchar2,因為varchar2精度比nvarchar2小,所以需要將varchar2轉換為nvarchar2型別,由於varchar2是左值,對索引列做了函式操作(SYS_OP_C2C),導致不能用到這個索引,因此是全表掃描,
SQL> var p nvarchar2(200);
SQL> exec :p := 'a';
PL/SQL procedure successfully completed.
SQL> select * from test where object_name = :p;
no rows selected
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 388 (100)| | 0 |00:00:00.04 | 1396 |
|* 1 | TABLE ACCESS FULL| TEST | 1 | 16 | 388 (1)| 00:00:05 | 0 |00:00:00.04 | 1396 |
--------------------------------------------