`

万恶的隐式数据类型转换

阅读更多
2年前上线的系统了,运行两年了啊(意思是忍受了这么慢的查询很久了)!!!
——正式开始之前,先吐吐槽。。。。。

场景描述:系统中查询条件涉及日期的所有操作,都会导致数据库IO开销突增。
-------------------------------------------------------------------------
解决过程:
  0.检查日期字段,看其上有无索引,这个是有的
  1.拉下来项目代码,配置jrebel,配置log4j,启动项目
  2.登录系统,查询,拉取控制台SQL,手动补齐参数值,执行,看执行计划。速度快开销小,木发现有大问题…… 纳闷。。。。。不解。。。。。
  3.设置log4j,重启项目,重新执行2:
    1)修改
       log4j.rootLogger=INFO, stdout
    2)新增
       log4j.logger.org.hibernate.type=TRACE
       log4j.logger.org.hibernate.sql=TRACE
  4.查看对日期字段绑定的日期值的类型,竟然是TimeStampType!!!肿么会这样???传进去的值明明是Date类型的。。。。。这样查询不会走索引,而且要把日期列的每个值都转换成时间戳类型再跟传入的值比较。。。。。介个隐式数据类型转换也太神奇了吧
  5.将所有类似
     hql.append(" and table_name.d_column_name = :d_column_name");
    的语句改为
     hql.append(" and table_name.d_column_name = cast(:d_column_name as date)");
    这样虽然我Trace到的还是TimeStampType,但是在查询里转换成Oracle DATE类型了,就可以走索引了。
    问题解决。
-------------------------------------------------------------------------
疑惑:
  1.出现这种问题原因是什么?肯定不是日期格式的问题,因为要在页面上设定日期范围的查询,虽然传入字符串并转为短日期格式传入,最后Trace到的还是时间戳类型。不明白,hibernate明明是有DateType的啊。
  2.有没有方法可以通过配置hibernate一次性解决这种日期类型转换为时间戳类型的问题?
  以上两个疑惑,苦逼DBA问过开发,他们也不知道……

后记:EM中也可以排查到这个问题:Advisor Central>Advisors>Advisor Tasks>Advisory Type = SQL Tuning Advisor > Go > View Result > Overall Task Statistics > Restructure SQL > Select one line> View Recommendations
Type
  Restructure SQL
Findings
  The predicate "table_name"."d_column_name"=:B1 used at line ID 6 of the execution plan contains an implicit data type conversion on indexed column "d_column_name". This implicit data type conversion prevents the optimizer from selecting indices on table "user_name"."table_name".
Recommendations
  Rewrite the predicate into an equivalent form to take advantage of indices.
Rationale
  The optimizer is unable to use an index if the predicate is an inequality condition or if there is an expression or an implicit data type conversion on the indexed column.
很明白对吧,谓词"table_name"."d_column_name"=:B1 包含对已加索引的日期列d_column_name上的隐式数据类型转换,导致无法使用索引,于是乎,数据量大了之后,杯具就发生了。。。。。

P.S.(真啰嗦啊)之前的项目用SQL Server数据库,并无此问题。原因是'2012-02-01 00:00:00'这种日期格式,SQL Server可以直接识别,如果日期列上加了索引,则可走索引。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics