最近在做一个简单的管理系统 , 在最后收尾时数据库里的记录增大到200万时,分页查询时发现速度非常慢,一直在找原因 , 起初以为是hibernate的问题,后来跟踪源码到jdbc层次发现不是hibernate的原因.下面贴出部分代码 .
getHibernateTemplate().execute(
new HibernateCallback<List<LoginLogDTO>>() {
@Override
public List<LoginLogDTO> doInHibernate(Session session)
throws HibernateException, SQLException {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder
.append("select ll.log_id , ll.uuid , m.product_name , p.platform_name , ll.create_time ");
sqlBuilder
.append(" , ll.operate_type , ll.soft_vers_no ");
sqlBuilder
.append(" from t_login_log ll left join t_model_platform mp on ll.mode_plat_id=mp.mode_plat_id ");
sqlBuilder
.append(" left join t_model m on mp.model_id = m.model_id ");
sqlBuilder
.append(" left join t_platform p on p.platform_code = mp.platform_code where 1=1 ");
// 搜索条件
if (StringUtils.equals(findTypes[0], findType)) {
sqlBuilder.append(" and ll.uuid=:numValue");
}
else if (StringUtils.equals(findTypes[1], findType)) {
sqlBuilder
.append(" and m.product_name=:stringValue");
}
else if (StringUtils.equals(findTypes[2], findType)) {
sqlBuilder
.append(" and p.platform_name=:stringValue");
}
else if (StringUtils.equals(findTypes[3], findType)) {
sqlBuilder
.append(" and ll.operate_type=:numValue");
}
// date
if (startDate != null) {
// sqlBuilder.append(" and ll.create_time >= :startDate ");//慢的写法
sqlBuilder.append(" and ll.create_time >=to_date(:startDate , 'yyyy-mm-dd hh24:mi:ss') ");
}
if (endDate != null) {
// sqlBuilder.append(" and ll.create_time <= :endDate ");
sqlBuilder.append(" and ll.create_time <=to_date(:endDate , 'yyyy-mm-dd hh24:mi:ss') ");
}
try {
Query query = session.createSQLQuery(sqlBuilder.toString()) ;
if(ArrayUtils.contains(findTypes, findType)){
if(StringUtils.equals(findTypes[0], findType)){
query.setLong("numValue", Long.valueOf(findValue)) ;
}
else if(StringUtils.equals(findTypes[3], findType)) {
if("登录".equals(findValue))
query.setShort("numValue", (short)1) ;
else if ("退出".equals(findValue)) {
query.setShort("numValue", (short)2) ;
} else {
query.setShort("numValue", (short)-1) ;
}
} else{
query.setString("stringValue", findValue) ;
}
}
if(startDate!=null){
// query.setTimestamp("startDate", startDate) ; //njl
query.setString("startDate", DateFormatUtils.format(startDate, "yyyy-MM-dd HH:mm:ss")) ;
}
if(endDate!=null){
// query.setTimestamp("endDate", endDate) ;
query.setString("endDate", DateFormatUtils.format(endDate, "yyyy-MM-dd HH:mm:ss")) ;
}
query.setFirstResult(firstResult) ;
query.setMaxResults(maxResults) ;
List<LoginLogDTO> llList = new ArrayList<LoginLogDTO>() ;
long start = System.currentTimeMillis() ;
List<Object[]> result = query.list() ;
log.debug("query login log spend: " + (System.currentTimeMillis() - start) + "ms") ;
return llList;
} catch (NumberFormatException e) {
e.printStackTrace();
throw new IllegalArgumentException() ;
} catch (HibernateException e) {
log.error("query login log error ") ;
e.printStackTrace() ;
throw new DAOException(e) ;
}
}
});
t_login_log表中有200万条记录 , 其它表中数据很少
如果在设置参数时 , 使用query.setTimestamp("startDate" , startDate) ;要花费2000ms如果改成上面的写法用了4ms左右.
记录一下 , 可能不