一个Date类型的ibatis查询走不上索引的问题

3 篇文章 0 订阅
 

遇到过一个Date类型作为条件查询走不上索引的问题,分析下原因:

 

以下为简化后的场景:通过时间范围作一个邮件发送数量的统计

java:

 

import java.util.Date;

public List<Object> listRecentTaskInfoByStatus( Date start, Date end,String sendType) {

        Map<String,String> paraMap = new HashMap<String,String>();

        paraMap.put(TASK_STAT_START_TIME, start);

        paraMap.put(TASK_STAT_END_TIME, end);

        return defaultDao.getObjList(nameSpace.get(sendType), paraMap, "CHANNEL_RECENT_STAT");

}


ibatis:

 

<select id="SELECT_CHANNEL_RECENT_STAT" resultMap="MtnPlanSendlog_RM_CHANNEL_TASK" parameterClass="java.util.HashMap">


<![CDATA[

SELECT /*+index (a SENDLOG_GSEND_IND)*/

                overview_id,

                count(*) as tmp_count

         FROM

                MTN_PLAN_SENDLOG a

         WHERE

                is_deleted = 'n'

                and overview_id is not null

                and GMT_SEND >= #startTime#

                and GMT_SEND < #endTime#

                GROUP BY overview_id

  ]]>


</select>



现象:

sql查询缓慢,DBA观察发现没有走上GMT_SEND的索引


 

原因:

由于需要小时分秒的信息,我们使用的是java.util.Date,观察发现在数据库端有类似如下函数转换

TO_TIMESTAMP(date_column) = parameter_timestamp

导致纵然加了hit也走不上索引.

为什么会触发oracle做隐式转换呢?因为在ibatis的处理中,java.util.Date会转换为java.sql.Timestamp(具体原因可以参考java.sql.PreparedStatement和相关文档,在此不详述)

ps.setTimestamp(i, new java.sql.Timestamp(((Date) parameter).getTime()));

 

JAVA传下去的是Timestamp,而数据库的类型是Date,根据oracle的策略,会对date类型做强制转换TO_TIMESTAMP(GMT_SEND),因此就走不上索引了 。


解决方案:

经过网上查询以及和郑隐、肖建冰、胡伟军同学的讨论,认为可选且比较靠谱的解决方案主要有3种:

1.  将数据库的列改为timestamp(风险较太大)

2. 使用to_date('2011-03-08 15:45:43.123','yyyy-mm-dd HH24:MI:SS....')

3. 将传入参数由java.util.Date转换为String,然后在ibatis端使用to_date函数解决    

 and GMT_SEND >= to_date(#startTime#,'YYYY-MM-DD HH24:MI:SS')


 

实际过程中采用第3钟解决的
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值