Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1339703
  • 博文数量: 169
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3800
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-30 13:00
个人简介

About me:Oracle ACE pro,optimistic,passionate and harmonious. Focus on ORACLE,MySQL and other database programming,peformance tuning,db design, j2ee,Linux/AIX,Architecture tech,etc

文章分类

全部博文(169)

文章存档

2024年(24)

2023年(28)

2022年(43)

2020年(62)

2014年(3)

2013年(9)

分类: Oracle

2023-05-08 16:52:21

 隐式类型转换会导致列上的索引用不上,一般是类型不一致导致的,比如:
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) |
给主人留下些什么吧!~~