论坛首页 Java企业应用论坛

发疯Hibernate分页问题,性能优化!

浏览 39751 次
精华帖 (2) :: 良好帖 (0) :: 新手帖 (18) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-07-25   最后修改:2009-02-07

最近写了一个Hibernate分页,之前用游标来实现得到count 总行数..用HQL语句查询!可是现在问题出现了,但数据达到海量的时候,出现比较慢,现在要进行优化:

1.不能使用游标得到count总行数!

ScrollableResults rs = query.scroll(ScrollMode.SCROLL_INSENSITIVE);
  rs.last();
  return (rs.getRowNumber() + 1);

2.不能使用select count(*) from .....这样要得到count 和list 分布操作很麻烦!查询和count 都要同步!不想两次操作...

假如更改字段都要更改...不想这么做!要公用....

3.不能使用query.list().size()

 int count=query.list().size();

除了这三种方法实现得到count,不知道还能用什么方法去实现!相信javaeye上面大师们应该会出现这样情况吧!遇到过的提提建议...

   发表时间:2008-07-25  
是分页有性能问题,还是取总记录数有性能问题?有没有试过用Query的setFirstResult和setMaxResults方法来实现分页?
0 请登录后投票
   发表时间:2008-07-25  
movingboy 27 分钟前
是分页有性能问题,还是取总记录数有性能问题?有没有试过用Query的setFirstResult和setMaxResults方法来实现分页?

是取总记录数有性能问题哈?我就是用Query的setFirstResult和setMaxResults方法来实现分页?又没什么好方法来实现得到count总记录数!
  谢谢!
0 请登录后投票
   发表时间:2008-07-25  
myprincejava 写道
movingboy 27 分钟前
是分页有性能问题,还是取总记录数有性能问题?有没有试过用Query的setFirstResult和setMaxResults方法来实现分页?
  

是取总记录数有性能问题哈?我就是用Query的setFirstResult和setMaxResults方法来实现分页?又没什么好方法来实现得到count总记录数!
   谢谢!

0 请登录后投票
   发表时间:2008-07-25  
lz用的什么数据库?又是什么驱动?
看看http://www.iteye.com/topic/9881?page=1
除了count(*),还可以用服务器端游标的,不过跟数据库驱动实现有关
0 请登录后投票
   发表时间:2008-07-25  
建议总数可以缓存一下
0 请登录后投票
   发表时间:2008-07-25  
如果是动态查询,总数是变动的,无法缓存。

暂无办法,唯有数据库 performance tuning or query tuning。
0 请登录后投票
   发表时间:2008-07-25  
我觉得老老实实用select count(*) from ...就好了,但你已经说不能这样用,我就没办法了
0 请登录后投票
   发表时间:2008-07-25  
只有第二种方法最现实,然后继续缓存优化,缓存时间可以缩小到5秒级的,可解决并发问题,5秒延时大多数状态下都是能够接受的。

第二种的HQL的通用实现,请参考SpringSide2的源代码。


org.springside.core.dao.HibernateGenericDao
         
/**分页查询函数,使用hql
 * @param hql String
 * @param values Object[]
 * @param pageParam 页面查询参数
 * @param alias 排序表的别名,排序的时候才起作用
 * @return Page(totalProperty, list)
 */
public Page findPage(String hql, Object[] values, PageParam pageParam, String alias) {
    Assert.hasText(hql);
    Assert.notNull(pageParam);
    if (values == null) {
        values = new Object[] {};
    }
    // Count查询
    String countQueryString = "SELECT COUNT(*) " + 
        HqlUtils.removeSelect(HqlUtils.removeOrders(hql));
    long totalCount = ((Long) getHibernateTemplate().find(countQueryString, values)
        .get(0)).longValue();
    if (StringUtils.isNotEmpty(pageParam.getSort())) {
        Assert.hasText(alias);
        hql = HqlUtils.removeOrders(hql);
        hql += " ORDER BY " + alias + "." + pageParam.getSort();
        if (pageParam.getDir().equals(PageParam.DIR_ASC)) {
            hql += " ASC";
        } else {
            hql += " DESC";
        }
    }
    // 实际查询返回分页对象
    Query query = createQuery(hql, values);
    query.setFirstResult(pageParam.getStart());
    query.setMaxResults(pageParam.getLimit());
    List list = query.list();
    return new Page((int) totalCount, list);
}

1 请登录后投票
   发表时间:2008-07-25  
同时提醒,楼主的第一和第三种方法几乎是无法用在生产环境的,性能太差了,是绝对要避免出现的。

除非记录数在100以下,但是一般都会使用通用接口,所以即使适用小数据量也是没有太大的实际开发意义。
1 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics