隐式转换(Implicit Conversion)就像他的名字一样,是个隐秘、不容易被发现的问题,但归根结底,还是设计开发中未遵守相关的规范,或者说是不良的设计开发习惯所导致的。

如果在条件中的字段和变量类型不一致,数据库会按照低精度向高精度的顺序进行隐式转换,转换的过程就会消耗资源,例如CPU,但是更关键的是如果隐式转换的字段是索引列,就会导致因使用了函数而不能用到索引,该使用索引扫描的执行计划就变成了全表扫描,这对系统性能来说就是潜在的风险。

例如在Oracle中,类型转换如下,

[转帖]见识一下SQL Server隐式转换处理的不同_类型转换

字符串类型转换关系,

[转帖]见识一下SQL Server隐式转换处理的不同_隐式转换_02

测试表test的object_name是varchar2类型,subobject_name是nvarchar2类型,都创建了索引,

代码语言:javascript

复制

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),导致不能用到这个索引,因此是全表扫描,

代码语言:javascript

复制

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 |
----------------------------------------