好久不见,绑定变量发生隐式类型转换性能优化案例分享

文章讲述了在高并发场景下,SQL绑定变量引发的隐式类型转换问题,通过排查数据库等待事件和执行计划,发现SYS_OP_C2C函数的存在。建议修改字段类型或创建函数索引以提高查询效率,同时提供检测隐式转换的SQL查询方法。
摘要由CSDN通过智能技术生成

        欢迎关注“数据库运维之道”公众号,一起学习数据库技术!

        本期将为大家分享“SQL语句绑定变量发生隐式类型转换”的性能优化案例。

        关键词:direct path read、SYS_OP_C2C、隐式类型转换

        客户反馈业务系统卡住了,DBA检查数据库发现某条高并发的SQL语句出现隐式类型转换,导致执行计划无法走索引定位数据。

SELECT 字段1,字段2,字段3 
 FROM "YWZD"."TEST01" "T"
 WHERE ("T"."infoId" = :EntityKeyValue1)
Bind Variables :
 1 -  (NVARCHAR2(32)):bvh576sp8w

        首先,DBA接到用户报障后,第一反应就是查询数据库等待事件,包括当前活动会话event统计信息、近1小时哪条语句执行频繁最高。

set linesize 150
set pagesize 500
col event for a40
col event_info for a100
select inst_id,event,count(*) cnt
from gv$session
where wait_class <> 'Idle'
group by inst_id,event
order by count(*) desc;

    INST_ID EVENT                       CNT
---------- ---------------------------------------- ----------
     1 direct path read                   195
     2 direct path read                   124
   
select 'last 1 hour event: '||event "event_info", sql_id, count(*)
  from v$active_session_history
 where sample_time > sysdate - 1 / 24
   and session_type = 'FOREGROUND'
   and wait_class <> 'Idle'
 group by event, sql_id
 having count(*)>100
 order by 3 desc;

               event_info                      SQL_ID         COUNT(*)
-------------------------------------------- ------------- ----------
last 1 hour event: direct path read          71cva5kkk3wd8     164480
last 1 hour event: gc buffer busy release    1azfwx81dmy4r     6606

        通过上述的两条排查语句,可以快速定位到SQL_ID为71cva5kkk3wd8的SQL语句产生大量的direct path read事件。同时,将SQL语句反馈给开发单位。

        接着,检查SQL语句对应的执行计划,可以看到执行计划中出现“久违”的关键字“SYS_OP_C2C”,这个明显跟隐式类型转换有关系。SYS_OP_C2C 是一个内部函数,功能是将VARCHAR2的数据类型转换成国家字符集的NVARCHAR2类型,通过内部TO_NCHAR函数实现。

alter session set cursor_sharing=force;
set linesize 1000
set pagesize 999
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(to_char('&sql_id'),NULL));

set linesize 1000
col value_string for a30
col name for a30
select SQL_ID,NAME,POSITION,DATATYPE,DATATYPE_STRING,VALUE_STRING 
from V$SQL_BIND_CAPTURE WHERE SQL_ID = '&sql_id';

        最后,检查表结构对应的字段类型设计,结果看到字段类型为CHAR(10)。很明显字段类型与参数值类型不匹配,数据库优化器自动进行内部类型转换,进而导致全表扫描。

        (1)通过上述分析,我们建议开发单位修改字段的类型或者创建索引。开发单位为了尽快恢复业务,选择创建索引。

create index YWZD.IDX_infoId on "YWZD"."TEST01"(SYS_OP_C2C("infoId"));

        (2)创建函数索引后,查询效率得到明显改善与提升。重新验证执行计划,看到COST代价值10484下降至27。

        (3)如何找出其他存在隐式转换的SQL?可以对生产环境的SQL进行全面审查,杜绝大多数存在隐式类型转换的SQL。通过以下两条语句找出数据库中存在隐式转换的SQL。

SELECT
     SQL_ID,
     PLAN_HASH_VALUE
 FROM
     V$SQL_PLAN X
 WHERE
     X.FILTER_PREDICATES LIKE '%INTERNAL_FUNCTION%'
 GROUP BY
     SQL_ID,
     PLAN_HASH_VALUE;


SELECT
     SQL_ID,
     PLAN_HASH_VALUE
 FROM
     V$SQL_PLAN X
 WHERE
     X.FILTER_PREDICATES LIKE '%SYS_OP_C2C%'
 GROUP BY
     SQL_ID,
     PLAN_HASH_VALUE;

        通常ORACLE数据库存在显式类型转换(Explicit Datatype Conversion)和隐式类型转换(Implicit Datatype Conversion)两种类型转换方式。如果进行比较或运算的两个值的数据类型不同时(源数据的类型与目标数据的类型),而且此时又没有转换函数时,那么ORACLE必须将其中一个值进行类型转换,使其能够运算。这就是所谓的隐式类型转换。其中隐式类型转换是自动进行的,当然,只有在这种转换是有意义的时候,才会自动进行。

create table TEST01 as select * from dba_objects;
create index ix_object_name on TEST01(object_name);
variable v_object_name nvarchar2(32);
exec :v_object_name :='OBJ$';
select count(*) from TEST01 where object_name=:v_object_name;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);

        以上就是本期关于“SQL语句绑定变量发生隐式类型转换”的性能优化案例分享。希望能给大家带来帮助。

        欢迎关注“数据库运维之道”公众号,一起学习数据库技术!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值