隐式类型转换会导致列上的索引用不上,一般是类型不一致导致的,比如:
1)where varchar2_column = number_value,会将varchar2的列使用to_number进行转换。
2)where varchar2_column = nvarchar2_value,会将varchar2列使用SYS_OP_C2C进行转换。
3)where date_column = timestamp_value,会对date类型列使用INTERNAL_FUNCTION进行转换。
例如:
dingjun123@ORADB> select * from implicit_tab where id = 1;
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
Plan hash value: 937183765
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 52 | 2 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| IMPLICIT_TAB | 1 | 52 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TO_NUMBER("ID")=1)
如果在SQL中使用绑定变量,要确保绑定变量类型与列类型一致,否则可能会发生隐式类型转换导致索引用不上。
那么如何查找有问题的隐式转换SQL呢,在ORACLE里是很困难的,ORACLE没有针对SQL语句记录是否发生implicit conversion,只能通过执行计划大体来判断,一般来说,索引列发生隐式类型转换才是我们要关注的,也就是发生了隐式类型转换,且对应的列是索引列。
大体的查找过程如下所示:
1)先按照发生隐式类型转换的情况,到v$sql_plan里去找
select * from (
select sql_id,sql_fulltext,module,parsing_schema_name,executions,buffer_gets/decode(executions,0,1,executions) avg_gets,
cpu_time/decode(executions,0,1,executions)/1000000 avg_cpu_time,elapsed_time/decode(executions,0,1,executions)/1000000 avg_elasped_time,
rows_processed/decode(executions,0,1,executions) rowproc,row_number() over(partition by FORCE_MATCHING_SIGNATURE order by sql_id) rn,
count(*) over(partition by FORCE_MATCHING_SIGNATURE) cnt
from v$sql where sql_id in (
select sql_id
from v$sql_plan a
where a.OPERATION = 'TABLE ACCESS'
and a.OPTIONS like 'FULL'
and (a.FILTER_PREDICATES like '%TO_NUMBER(%' or
a.FILTER_PREDICATES like '%TO_CHAR(%' or
a.FILTER_PREDICATES like '%TO_DATE(%' or
a.FILTER_PREDICATES like '%TO_TIMESTAMP(%' or
a.FILTER_PREDICATES like '%INTERNAL_FUNCTION(%' or
a.FILTER_PREDICATES like '%SYS_OP_C2C(%'
)
)
) where rn=1
order by cnt desc,avg_cpu_time desc ;
这条语句只能大体找到一些隐式类型转换的语句。
2)要解析发生隐式类型转换的列,并且是索引列 dba_ind_columns
这个解析比较复杂,可能需要用到正则表达式,这里不在研究。
希望ORACLE后续版本可以记录implicit conversion,这样查询起来就比较简单了。
阅读(1408) | 评论(0) | 转发(0) |