首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

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

2012-10-30 
发疯Hibernate分页问题,性能优化!最近写了一个Hibernate分页,之前用游标来实现得到count 总行数..用HQL语

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

最近写了一个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上面大师们应该会出现这样情况吧!遇到过的提提建议...



其中这个removeOrders 和 removeSelect 谁能告诉我一下有什么用处么? 谢谢

还有关于这种海量数据分页的问题,如果不是很在意总数的实事性,是否可以只在第一次查询的时候就算出count,后面的查询只查询内容而不用再次计算count呢?

即第一次查询:

1·查处满足sql条件的所有记录数目 ( count(*) )
2·返回前100条数据


第二次查询(即表示层调用了翻页)
1·查询满足sql条件的第101~200条记录


.....

第n次查询(查找到最后一页)
1·查询满足sql条件的第1000~1200条记录(假设count*的结果是1200)

请问是这样一个过程么 ? 谢谢这个就可以算总数了,ORDER BY 其实不去掉也没事吧。这个就可以算总数了,ORDER BY 其实不去掉也没事吧。

SpringSide就是这么做的,order by不去掉,可能会浪费无谓的排序计算吧。 65 楼 soci 2008-08-20   这个方法不知道多个JOIN TABLE会不会有问题
我的感觉,分页这东西很鸡肋的,还不如像BLOG那样 搞个日历,通过日期访问记录更有意义。
66 楼 iamzealotwang 2008-08-20   能看一下我那个问题么? 谢谢了

67 楼 soci 2008-08-20   iamzealotwang 写道能看一下我那个问题么? 谢谢了


removeOrders 和 removeSelect 方法注释很明白了,前一个去掉ODER BY 后一个去掉 SELECT XXXX
只取中间的from xxx where xx 作为计算COUNT的条件

回到主贴 我还是认为如果海量数据要分页这个需求要灵活些
比如你是新闻网站,最好按日期列出新闻
如果是小说网站,比如给红楼梦分页,那就上一页下一页就可以或者按书的章节分。
如果是论文检索网站,你可以先按年度分页。
总之有很多办法把取总数这个问题绕过去。 68 楼 icewubin 2008-08-20   soci 写道这个方法不知道多个JOIN TABLE会不会有问题
我的感觉,分页这东西很鸡肋的,还不如像BLOG那样 搞个日历,通过日期访问记录更有意义。


join table不会有问题,这个方法我已经在两个项目中用了半年多了。
69 楼 iamzealotwang 2008-08-20   引用
removeOrders 和 removeSelect 方法注释很明白了,前一个去掉ODER BY 后一个去掉 SELECT XXXX
只取中间的from xxx where xx 作为计算COUNT的条件


明白了 谢谢了。


引用
关于这种海量数据分页的问题,如果不是很在意总数的实事性,是否可以只在第一次查询的时候就算出count,后面的查询只查询内容而不用再次计算count呢?

即第一次查询:

1·查处满足sql条件的所有记录数目 ( count(*) )
2·返回前100条数据


第二次查询(即表示层调用了翻页)
1·查询满足sql条件的第101~200条记录


.....

第n次查询(查找到最后一页)
1·查询满足sql条件的第1000~1200条记录(假设count*的结果是1200)


那关于这点,我想的对么? 麻烦您了。
70 楼 soci 2008-08-20   总数保存可以的,很多人这么用。 71 楼 xudong82113 2008-08-20   burt 写道ecsun 写道count(*)一般来说会损失一些性能,加上first和max以后,基本可以不考虑损失的性能,如果实在能count(*)性能不满意
或以改为count(id),这种方式比count(*)性能要好一些
可以拿你的海量数据测一下,就明白了.

同时,如果真的数据量太海量了,count也就意义不大了.这时候可以这么做,比如每一次取出1000条记录,放前台去分页,当然,是不是一次1000条,要看你的访问压力了.

因为频繁访问海量数据,本身对数据库已经是一个很大的压力了,为了每次取得10条一页的数据,去访问一次数据库,划不来,一次多取一点,展现完了再去后台取.



用mssql,4300万的数据,相比select count(*),select count(id)并没有多大提升。
还是4分钟36秒左右。




4300万太过了, 我查看过资料, mysql在单表情况下, 1500万还能保持一个比较高的读写速度, 超过这个数量级, 性能就开始拐点下降了。 72 楼 murainwood 2008-08-21   4300万条?
一张表么?还不拆? 73 楼 icewubin 2008-08-21   murainwood 写道4300万条?
一张表么?还不拆?

银行项目还有百亿级的呢。

表只是个抽象概念,底层可以水平分区或者垂直分区的,上层未必要拆的。
74 楼 nowonder 2008-08-21   mysql的表分区貌似一直都很烂 75 楼 usomething 2008-08-22   同意caohj的说法,我的想法是用spring的AOP拦截Dao的所有方法,一旦方法以remove开头则肯定是删除记录,一旦方法以add开头则是删除记录,hibernate在执行方法的时候会返回一个int值,意义是影响的行数,在Context环境中维护一个static的总数值,一旦AOP拦截器起作用则此static总数值跟着发生变化!说的可能不清楚,我演示一下

Dao某方法:
public int addProduct(List<Product> products){
    //具体实现方法,建议使用hibernate的批量插入
}

此方法被Spring拦截到在其拦截器中有一下代码
private static Long total=0L;

public void modifyTotal(int i){
  total+=(long)i;
}

如果你记录数实在多得惊人,建议一改变total后立即存入一个文件中或一个字段中! 76 楼 iamzealotwang 2008-08-23   引用
同意caohj的说法,我的想法是用spring的AOP拦截Dao的所有方法,一旦方法以remove开头则肯定是删除记录,一旦方法以add开头则是删除记录,hibernate在执行方法的时候会返回一个int值,意义是影响的行数,在Context环境中维护一个static的总数值,一旦AOP拦截器起作用则此static总数值跟着发生变化!说的可能不清楚,我演示一下


1·remove方法一定是删除,add方法一定是添加。不过Dao的remove和add一定就只删除更改1条记录么?
   要是级联咋办?要是saveUpDate呢?我怎么知道他是save了,还是仅仅update了?

这个我觉得应该在数据库触发器里面做文章,那样保险。

2·记录共享 static ,数据量小的时候没有意义,对不?大的时候又需要读取文件。这里否存在进程之间的并发现象?就是操作系统里面读写者问题?

3·对于一般性查询语句,我认为记录总数是没有意义的 是吧?

热点排行