`
myprincejava
  • 浏览: 31129 次
  • 性别: Icon_minigender_1
  • 来自: 来自太平洋
社区版块
存档分类
最新评论

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

分享到:
评论
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·对于一般性查询语句,我认为记录总数是没有意义的 是吧?
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后立即存入一个文件中或一个字段中!
74 楼 nowonder 2008-08-21  
mysql的表分区貌似一直都很烂
73 楼 icewubin 2008-08-21  
murainwood 写道
4300万条?
一张表么?还不拆?


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

表只是个抽象概念,底层可以水平分区或者垂直分区的,上层未必要拆的。
72 楼 murainwood 2008-08-21  
4300万条?
一张表么?还不拆?
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万还能保持一个比较高的读写速度, 超过这个数量级, 性能就开始拐点下降了。
70 楼 soci 2008-08-20  
总数保存可以的,很多人这么用。
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)


那关于这点,我想的对么? 麻烦您了。
68 楼 icewubin 2008-08-20  
soci 写道
这个方法不知道多个JOIN TABLE会不会有问题
我的感觉,分页这东西很鸡肋的,还不如像BLOG那样 搞个日历,通过日期访问记录更有意义。


join table不会有问题,这个方法我已经在两个项目中用了半年多了。
67 楼 soci 2008-08-20  
iamzealotwang 写道
能看一下我那个问题么? 谢谢了


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

回到主贴 我还是认为如果海量数据要分页这个需求要灵活些
比如你是新闻网站,最好按日期列出新闻
如果是小说网站,比如给红楼梦分页,那就上一页下一页就可以或者按书的章节分。
如果是论文检索网站,你可以先按年度分页。
总之有很多办法把取总数这个问题绕过去。
66 楼 iamzealotwang 2008-08-20  
能看一下我那个问题么? 谢谢了

65 楼 soci 2008-08-20  
这个方法不知道多个JOIN TABLE会不会有问题
我的感觉,分页这东西很鸡肋的,还不如像BLOG那样 搞个日历,通过日期访问记录更有意义。
64 楼 icewubin 2008-08-20  
soci 写道
这样行不:
hql作为分页类的参数,方法签名:
listByPage(String hql,Page page)

int position = hql.toLowerCase().indexOf("from");
String totalHql = "select count(*) as totals " + hql.substring(position);
这个就可以算总数了,ORDER BY 其实不去掉也没事吧。


SpringSide就是这么做的,order by不去掉,可能会浪费无谓的排序计算吧。
63 楼 soci 2008-08-19  
这样行不:
hql作为分页类的参数,方法签名:
listByPage(String hql,Page page)

int position = hql.toLowerCase().indexOf("from");
String totalHql = "select count(*) as totals " + hql.substring(position);
这个就可以算总数了,ORDER BY 其实不去掉也没事吧。
62 楼 iamzealotwang 2008-08-19  
    /**
     * 去除hql的select 子句
     * @param hql
     * @return hql
     */
    public static String removeSelect(String hql) {
        Assert.hasText(hql);
        int beginPos = hql.toLowerCase().indexOf("from");
        Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
        return hql.substring(beginPos);
    }
    /**
     * 去除hql的orderby 子句
      * @param hql
     * @return hql
     */
    public static String removeOrders(String hql) {
        Assert.hasText(hql);
        Pattern pattern = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*"
            , Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(hql);
        StringBuffer buf = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(buf, "");
        }
        matcher.appendTail(buf);
        return buf.toString();
    }


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

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

即第一次查询:

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


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


.....

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

请问是这样一个过程么 ? 谢谢
61 楼 litianyi520 2008-08-19  
不行就用lucence 吧~ 索引文件搞~ 查库啥时候都慢~
60 楼 lu_pp 2008-08-19  
caohj 写道
建议用一个字段来存储count数,当有增加一条记录时count数+1,删除对应的一条记录时,count -1,查询分页的取count数时候直接去取一个字段记录就可以了.

按不同条件进行查询的话,好象就不好用了
我是使用SELECT COUNT 来返回总数
59 楼 。。。 2008-08-19  


放一个List getPage(int page)的方法出来,如果返回的list是empty的, 给用户弹个对话框就说找不着了。至于跳转....提供首尾页和上下翻的按钮, 再提供一个页码输入框......大不了我不告诉你到底有多少记录.....
一定要计算Count的话,尽量避免count(*)的出现。


不过我实际环境中还没用过这种方法. 只是一个想法。

计算Count数据库可能有点小负担,而且还是count(*)。
58 楼 coolenhai 2008-08-19  
[align=left][/align][size=x-small][/size][b][/b]
引用
引用
57 楼 我不知道 2008-08-07  
4300万的数据 用户不可能查出这么多的数据,1页1页的翻着看吧。
我要是用户我准是疯了。

可能给用户分页100页,每页100条(那就是100×100=10000条),就已经疯了。当然,有时候他想知道总数,那就给他提供一个可查看总数的地方。不过我认为,分页这里没有几个用户分了100页,1页1页看的。

所以可以考虑在查询条件方面限制用户查出那么多的数据,比如用户必须选择某个查询条件等。
而且,只在第1次访问的时候计算总数,其他翻页的时候把总数和分页数等传过去好了。

相关推荐

    47-Java性能调优实战.zip

    模块七实战演练场则提供了实际场景下的调优实践,帮助学习者将理论知识转化为实际操作经验,解决真实世界中的性能问题。 最后,结束语部分可能总结了整个调优过程中的经验和教训,强调持续学习和实践的重要性。 综...

    额发疯埃尔法未发生阿萨德sad

    额发疯埃尔法未发生阿萨德sad

    一个让人发疯的小礼物

    标题中的“一个让人发疯的小礼物”似乎暗示着这是一款具有独特特性的软件,它可能在初接触时会带来一些挑战或困惑,但最终会给用户带来惊喜和乐趣。描述中的“最后让人开心的礼物”进一步确认了这款软件的娱乐性质,...

    70年代发疯的时代里最正常的艺术家.docx

    70年代发疯的时代里最正常的艺术家.docx

    QixRemake:406发疯了

    QixRemake是一款基于经典游戏Qix的重制版,而"406发疯了"这个描述可能指的是在游戏开发或者运行过程中遇到的一个特定问题,可能是版本号、错误代码或者是某种特定情况的表现。在Python编程中,这样的描述可能意味着...

    英语小组名称和口号精选.doc

    - "要成功,先发疯,下定决心往前冲!" 这些口号体现了坚持不懈、勇往直前、积极进取的精神。它们鼓励人们克服困难,坚信通过努力可以实现目标。无论是学习小组还是其他类型的团队,这些励志的话语都可以激励成员...

    从 0 开始带你成为消息中间件实战高手.zip

    文件“37 基于MQ实现订单系统的核心流程异步化改造,性能优化完成!”探讨了如何利用MQ来优化订单处理流程,提高系统性能。 接着,我们需要掌握MQ的集群建设和压力测试。文件“34 授人以渔:你们公司的MQ集群做过...

    LegacyFactions:Factions 1.6的高性能维护版本

    所有项目均保持开源状态,因此,如果有人想接管它们,请给我直接发送消息,以便我可以授予您访问该回购协议的权限,或者随意分叉它们-发疯! 大多数项目都足够稳定。 我将来可能会继续这些项目,但目前我也做不到。...

    2021关于高考学校横幅标语大全100句.docx

    2. **积极态度**:“主动的人在每一次忧患中都看到一个机会”,提醒学生面对困难时要积极寻找解决问题的办法,而不是被问题所困扰。 3. **持之以恒**:“狠抓基础是胜利的基础,持之以恒是胜利的保证”,强调长期...

    Scripts:一些脚本,分叉的,不要让我发疯!

    去做 很好地说明如何使用这些脚本 AddqBittorrentTrackers.sh 该脚本的目的是在qBittorrent torrent中注入木马,可以手动使用,也可以自动与Radarr / Sonarr一起使用。 实际上,由于API,这可以与qBittorrent v4.1 ...

    冰岛政治正确发疯!「Icelandic Political Correctness gone mad!」-crx插件

    用某些冰岛语替换某些冰岛语。 支持语言:English

    OnyX系统维护和配置

    Mac 用久了,也会有各种各样的问题。无用的日志/记录文件占据大量磁盘空间、字体缓存错乱导致界面字体发疯、磁盘权限出错导致文件无法打开等等等等。此时就需要“优化大师”、“超级兔子”之类的软件出马,清理或者...

    caiHongArchive:彩虹学发疯纪实录

    《caiHongArchive: 彩虹学发疯纪实录》 在信息技术领域,我们经常会遇到各种数据存储和传输的需求,而压缩包文件就是其中一种高效的方式。标题中的“caiHongArchive”很可能是一个自定义的或者特定项目的命名,代表...

    初中语文语文论文一个发疯的语文老师的帖子:感悟大师

    在当今教育界,语文教育一直占据着重要的位置。无论是对个人素养的培养,还是对文化传承的使命,语文教学都扮演着不可替代的角色。随着时代的发展,教育方式和理念也在不断创新与演变。在这样的背景下,三位中国语文...

    wenv:一个个人工作流程项目发疯了

    标题 "wenv:一个个人工作流程项目发疯了" 提示我们这可能是一个关于个人工作环境配置的项目,可能是为了优化Linux、Unix或者MacOS等操作系统中的终端体验。描述中的 "发疯了" 可能是指这个项目包含了大量自动化、...

    图像堆栈:获取3D图像文件,将其切成薄片,然后将生成的图像堆栈布置成一个漂亮的小蒙太奇。 添加蒙版和轮廓。 发疯!-matlab开发

    3D阵列,并在优化的网格中布置每个切片。 添加 遮罩和轮廓线可以使您的图像讲故事。 fig = IMAGEST(propertyArray)从中创建图像堆栈 propertyArray 无花果= IMAGEST(propertyArray,dataOptions,plotOptions...

    基于Web的系统的设计与实现

    在实际的Web系统开发中,优化资源使用、提升性能和保持用户体验的流畅性是非常关键的,这可能就是这个表述想要传达的含义。 【标签】"考试系统"表明我们将讨论的是一个特定类型的基于Web的系统,即用于在线考试的...

    ionic框架参考手册中文

    8. **性能优化**:由于混合应用的特点,性能优化是关键。手册会指导如何减少HTTP请求、优化资源加载、利用懒加载和使用IONIC Serve模式进行快速开发调试。 9. **打包与部署**:Ionic应用可以被编译为原生应用,然后...

    备战高考宣传标语.doc

    3. **目标设定**: 标语“要成功,先发疯,下定决心往前冲!”、“有大目标,须有大动作”鼓励设定明确的目标,并愿意付出巨大努力去实现。 4. **团队精神与协作**: “拧成一股绳,搏尽一份力,狠下一条心,共圆一个...

Global site tag (gtag.js) - Google Analytics