`

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

阅读更多

        实际工作中,发现Date类型作为条件查询走不上索引的问题,由于问题完全和http://blog.csdn.net/zldeng19840111/article/details/6721589一样,为简便起见,直接采用它的实例说明。

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

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类型则会自动解析为timestamp类型。具体原因可以参考java.sql.PreparedStatement和相关文档,在此不详述。

public void setParameter(PreparedStatement ps, int i, Object parameter, String jdbcType)   
    throws SQLException {   
  ps.setTimestamp(i, new java.sql.Timestamp(((Date) parameter).getTime()));   
}

        JAVA传下去的是Timestamp,如果数据库中时间字段是date类型,由于timestamp类型的精度比date类型的精度高,根据oracle的策略,所以oracle会对数据库里的date类型做强制隐身转换,将date类型转换为timestamp类型,由于加了函数,那么创建在date类型上的索引将不会使用到;(好像是oracle9i后开始才有的问题)。

 

解决方案:
        经过网上查询,认为可选且比较靠谱的解决方案主要有三种:
a.将数据库的列改为timestamp(风险较太大)
b.使用to_date('2011-03-08 15:45:43.123','yyyy-mm-dd HH24:MI:SS....')

to_date(to_char(#startTime#,'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS');

c.将传入参数由java.util.Date转换为String,然后在ibatis端使用to_date函数解决(改动点太多)

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

d.给GMT_SEND字段建函数索引(为了走索引而走索引,不是正常的解决问题的办法)

e.cast函数转成Date类型,最终是采用这种方案,对现有程序功能无影响且直接解决问题

and GMT_SEND >= cast(#startTime# as date)

 

附加知识说明:

table_name表的updated_date字段是DATE类型,并建立了索引

select * from table_name t where t.updated_date > to_timestamp('2015-12-01 01:20:30.123','YYYY-MM-DD HH24:MI:SS.ff');

        执行计划是全表扫描的

        而如下SQL:

select * from table_name t where t.updated_date > to_date('2015-12-01 01:20:30.123','yyyy-mm-dd HH24:MI:SS....');

select * from table_name t where t.updated_date > cast(to_timestamp('2015-12-01 01:20:30.123','YYYY-MM-DD HH24:MI:SS.ff') as date);

select * from table_name t where t.updated_date > to_date(to_char(to_timestamp('2015-12-01 01:20:30.123','YYYY-MM-DD HH24:MI:SS.ff'),'YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD HH24:MI:SS');

        执行计划是走索引的

        同理,如下SQL由于给t.updated_date多加了一个trunc,也会导致用不上索引而走全表扫描。

select * from table_name t where trunc(t.updated_date) > trunc(to_date('2015-12-01 01:20:30.123','yyyy-mm-dd HH24:MI:SS....'));

        可修改为:

select * from table_name t where t.updated_date > trunc(to_date('2015-12-01 01:20:30.123','yyyy-mm-dd HH24:MI:SS....'));

select * from table_name t where t.updated_date > to_date('2015-12-01 01:20:30.123','yyyy-mm-dd HH24:MI:SS....');
  • 大小: 2 KB
  • 大小: 2.3 KB
分享到:
评论

相关推荐

    Ibatis查询Id列表.doc

    根据提供的文档信息,我们可以深入探讨Ibatis框架中的一个具体应用场景:如何通过动态SQL查询特定条件下的ID列表。本文将从以下几个方面进行详细解析: ### 一、Ibatis简介 Ibatis是一个基于Java的持久层框架,它...

    操作数据库 iBATIS查询

    #### 一、iBATIS中的LIKE查询技巧 iBATIS是一款优秀的Java持久层框架,它简化了基于SQL的程序编写,避免了程序员手动处理结果集和手工编写SQL语句。在进行数据库查询时,LIKE查询是一种常见的需求,特别是在搜索...

    ibatis多表查询

    在这个例子中,我们将探讨如何使用Ibatis进行一对多的多表查询,以`book`和`user`两个表为例。 首先,我们有两个表:`book`和`user`。`book`表存储书籍信息,包含`oid`(主键)和`name`字段。`user`表存储用户信息,...

    Ibatis多表查询

    在这个例子中,我们将探讨如何在 Ibatis 中实现一对多的关系查询。 首先,我们创建了两个表:`book` 和 `user`。`book` 表存储书籍的信息,而 `user` 表记录作者信息,其中 `book_oid` 字段作为外键引用 `book` 表...

    Ibatis复杂查询语句.doc

    在Ibatis中,复杂查询通常涉及到多个表的联接、条件动态拼接、子查询以及各种数据类型的处理。文档"Ibatis复杂查询语句.doc"所展示的查询语句就是一个很好的例子,展示了Ibatis如何处理复杂的数据库操作。接下来,...

    ibatis_动态查询条件

    iBatis 是一个基于 Java 的持久层框架,它提供了动态查询条件的功能,可以根据不同的条件生成不同的 SQL 语句。在 iBatis 中,动态查询条件是通过 `&lt;dynamic&gt;` 元素来实现的,该元素可以根据参数的值来生成不同的 ...

    iBatis条件查询

    通过这样的例子,你可以看到如何在实际数据库模型上应用iBatis,比如如何处理各种类型的查询条件,如何进行分页查询等。 对于"ACCP Y2"这个标签,它可能指的是某种特定的课程或认证体系,可能是在学习路径的第二...

    iBatis一个小项目

    iBatis是一个轻量级的Java持久层框架,它的核心理念是将SQL语句与Java代码分离,使得开发者可以更加灵活地控制SQL的执行。在本项目中,我们将深入探讨iBatis的基本概念、配置、映射文件以及如何在实际应用中使用它。...

    第一个ibatis例子

    Ibatis,全称为MyBatis,是一个优秀的Java持久层框架,它主要负责SQL映射,使得开发者能够将注意力集中在编写SQL语句上,而无需关注JDBC代码的繁琐细节。这个"第一个ibatis例子"是一个典型的入门教程,旨在帮助初学...

    ibatis下oracle树查询

    在这个查询中,`START WITH`指定了查询的起始节点,`CONNECT BY PRIOR id = parent_id`表示当前行的父ID等于上一行的ID,从而形成树状连接。 然而,iBatis并不直接支持Oracle的CONNECT BY语法。因此,我们需要在...

    ibatis 文档查询

    在《iBATIS In Action》一书中,作者详细介绍了如何使用iBATIS进行高级查询技术,包括处理复杂的集合属性、映射关系的继承、语句类型和DDL(Data Definition Language),以及如何处理大规模数据集。 1. **使用...

    动态ibatis查询语句配置

    动态查询语句配置是Ibatis的一个重要特性,它允许我们在运行时根据业务需求构建灵活多变的SQL语句。这篇博文主要探讨的是如何在Ibatis中设置和使用动态SQL,以便实现更高效、更灵活的数据查询。 首先,我们需要理解...

    iBATIS模糊查询

    iBATIS模糊查询 iBATIS模糊查询是指使用iBATIS框架实现模糊查询的方法。模糊查询是指在数据库中搜索包含指定字符串的记录,通常...iBATIS模糊查询可以帮助开发者快速实现模糊查询功能,但需要注意安全性和性能问题。

    iBatis开发指南和一个iBatis实例

    iBatis是一个轻量级的Java持久层框架,它提供了SQL映射框架,将SQL语句与Java代码分离,使得数据库访问更为灵活和可控。在本压缩包中,你将找到一系列关于iBatis的学习资源,包括PDF文档、实例代码等,这些都是深入...

    ibatis 第一个程序

    标题 "iBatis 第一个程序" 暗示我们将探讨如何使用 iBatis,这是一个流行的持久层框架,用于简化 Java 应用程序中的数据库操作。iBatis 提供了一种方式,将 SQL 查询与应用程序代码分离,使得开发更加灵活且易于维护...

    ibatis的多参数查询.doc

    综上所述,在ibatis中实现多参数查询有多种方法,每种方法都有其适用场景。其中,使用Map容器的方法最为推荐,因为它既简单又安全,同时符合ibatis的设计理念。当然,在实际项目中,还需要根据具体需求选择最适合的...

    ibatis资料ibatis资料

    3. **实践项目**: 尝试在一个小项目中使用iBATIS,实践中遇到的问题会加深对iBATIS的理解。 4. **了解MyBatis**: 虽然iBATIS已被MyBatis取代,但两者有很多相似之处。了解MyBatis的新特性,如注解支持和更强大的...

    IBATIS开发使用实例

    提供的SQL查询语句展示了如何在一个特定的任务组ID(33295183)下,获取任务组的ID,并同时获取两种不同类型的覆盖范围(coverage)的描述。具体而言: 1. **多表连接**:通过`JOIN`关键字或内嵌`WHERE`子句实现多...

    ibatis的的增删改查和一对一、一对多查询

    在Java Web开发中,iBatis是一个非常流行的持久层框架,它将SQL语句与Java代码分离,提供了灵活的数据库操作方式。本篇文章将详细探讨iBatis在增删改查(CRUD)操作以及一对一和一对多关系映射中的应用。 首先,让...

Global site tag (gtag.js) - Google Analytics