美文网首页
oracle 根据时间范围查询缓慢问题排查解决

oracle 根据时间范围查询缓慢问题排查解决

作者: 杨文杰 | 来源:发表于2017-11-29 22:17 被阅读1555次

           今天生产环境上碰到个奇怪问题,在oracle数据库一个根据时间范围的查询语句居然执行了二十多分钟。一开始打印了执行sql日志之后就毫无反应了,任何错误都没有。把进程反复重启几次也一样。直到二十分钟后就出现了数据业务处理日志。表的数据量是千万级别,但是时间字段也加了索引的,不至于这么慢吧。查询的时间范围区间也就一分钟。
           实在想不出原因在哪里,就写个简单的查询语句试试:       

    select t.* from IMS_NTF_REMIND_HIS_201711 t where  t.SO_DATE>(sysdate-1/24/60) AND t.SO_DATE<sysdate
    

    奇迹发生,这个查询语句瞬间就出结果。马上查代码看查询语句怎么写的。

    String sql = "select t.* from " + tableName + " t  where " + " t.SO_DATE >=? and  t.SO_DATE < ?";
                if (logger.isDebugEnabled()) {
                    logger.debug("执行query的SQL:{}" , sql);
                }
                conn = ServiceManager.getSession().getConnection(dbAct);
                prepare = conn.prepareStatement(sql);
                prepare.setTimestamp(1, startTime);
                prepare.setTimestamp(2, endTime);
    

    从这个来看貌似也没发现什么问题,两条sql也没有什么区别。看一下数据库SO_DATE字段是date类型。至于为什么使用PreparedStatement.setTimestamp,是因为PreparedStatement.setDate();方法参数java.sql.Date的日期是没有时分秒的,
    不符合查询要求。这里想说明一点,oracle数据库字段是date类型的,普通jdbc查询出来的是不带时分秒的,java.util.Date才带时分秒。要有时分秒就要做个转换

                    HashMap<String, Object> map = new HashMap<String, Object>();
                    ResultSetMetaData metaData = rs.getMetaData();
                    int columns = metaData.getColumnCount();
                    for (int i = 1; i <= columns; i++) {
                        if ("DATE".equals(metaData.getColumnTypeName(i))) {
                            map.put(metaData.getColumnName(i), rs.getTimestamp(i));
                        } else {
                            map.put(metaData.getColumnName(i), rs.getObject(i));
                        }
                    }
                    rtn.add(map);
    

    言归正传,看到这里估计也猜出来了,oracle字段类型的隐式转换,将date类型转换为timestamp类型。导致索引失效,就会全表扫描,从而查询缓慢。知道问题所在解决就简单了,时间字符串,使用to_date()函数来转换字符串为日期和date做比较。改完之后重新测试查询速度变为了毫秒级别。

    总结:

    oracle date 和 timestamp类型混用时需要注意索引失效问题。如果oracle数据库字段是date类型,需要时分秒的就用字符串时间格式,使用to_date()函数转换做比较。不需要时分秒的就用java.sql.Date。

    相关文章

      网友评论

          本文标题:oracle 根据时间范围查询缓慢问题排查解决

          本文链接:https://www.haomeiwen.com/subject/xeppbxtx.html