`
myprincejava
  • 浏览: 31179 次
  • 性别: 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上面大师们应该会出现这样情况吧!遇到过的提提建议...

分享到:
评论
16 楼 myprincejava 2008-07-26  
nihongye 写道
很简单,大数据量,不要计算总数

你问题没看明白?现在就是要分页..怎么可能不得到count...
15 楼 myprincejava 2008-07-26  
sunsong 写道
你用的什么数据库?
MS SQLSERVER:,可以从系统表中快速获取
select rows from sysindexes where id = object_id(tablename) and indid in (0,1)
Oracle:
SELECT USER_TABLES.TABLE_NAME, USER_TABLES.NUM_ROWS FROM USER_TABLES USER_TABLES.NUM_ROWS COUNT
是否实时准确你可以测试一下,
实在不行,可以用触发器来维护一下用户表的记录数。

用Oracle9i....
14 楼 nihongye 2008-07-26  
很简单,大数据量,不要计算总数
13 楼 sunsong 2008-07-26  
你用的什么数据库?
MS SQLSERVER:,可以从系统表中快速获取
select rows from sysindexes where id = object_id(tablename) and indid in (0,1)
Oracle:
SELECT USER_TABLES.TABLE_NAME, USER_TABLES.NUM_ROWS FROM USER_TABLES USER_TABLES.NUM_ROWS COUNT
是否实时准确你可以测试一下,
实在不行,可以用触发器来维护一下用户表的记录数。
12 楼 myprincejava 2008-07-26  
<div class='quote_title'>ecsun 写道</div>
<div class='quote_div'>同时,这么大的数据量,要考虑cache了,数据库的性能,是所有系统最后的性能瓶颈所在, 考虑加cache吧</div>
<p><br/>是应该考虑这个.我想问假如用select count(*) from 去得到总记录数!请问你们是传两个对象还是?我觉得一个对象是不可能实现的!传两个对象(Query).难道页面查询了值还要分两次去查?分开写麻烦...贴下代码</p>
<p> </p>
<pre name='code' class='java'>public PageBeanInfo ctblshipfindAllshipByshipCd(PageBeanInfo page,HashMap map,boolean isLike)throws Exception
{
if(map==null)
    {
    throw new RuntimeException("HashMap not can null !");
    }

String langCd=(String)map.get("langCd");
String compCd=(String)map.get("compCd");
String shipCd=(String)map.get("shipCd");
String shipName=(String)map.get("shipName");
String shipType=(String)map.get("shipType");
String like_equals= isLike ? " like:":"=:";
String hql=" from CtblShip a join a.ctblShipNames b where ";

if(shipCd!=null&amp;&amp;!"".equals(shipCd))
{
shipCd=isLike ? shipCd.replace('*','%'):shipCd;
hql+="a.id.shipCd "+ like_equals +"shipCd and ";
}
if(shipType!=null&amp;&amp;!"".equals(shipType))
{
shipType=isLike ? shipType.replace('*','%'):shipType;
hql+="a.shipType "+ like_equals +"shipType and";
}
if(shipName!=null&amp;&amp;!"".equals(shipName))
{
shipName=isLike ? shipName.replace('*','%'):shipName;
hql+=" b.shipName "+ like_equals +"shipName and";
}
hql+="(a.deld is null or a.deld='F') and a.id.compCd=:compCd and b.id.langCd=:langCd";
Query query = getSession().createQuery(hql);
   if(shipCd!=null&amp;&amp;!"".equals(shipCd))
{
query.setString("shipCd", shipCd);
}
if(shipType!=null&amp;&amp;!"".equals(shipType))                                                                 
{
query.setString("shipType", shipType);
}                                                                                                                                                                                              
if(shipName!=null&amp;&amp;!"".equals(shipName))
{
query.setString("shipName", shipName);
}
query.setString("langCd",langCd)
      .setString("compCd",compCd);
//得到count,怎样去得到从页面传进来值
int count=PageUtil.getCount(hql,query);
page=PageUtil.createPage(page.getEveryPage(),page.getCurrentPage(),count);
query.setFirstResult(page.getBeginIndex())
              .setMaxResults(page.getEveryPage());
List&lt;CtblShip&gt; list=query.list();
     page.setResultList(list);
return page;

}</pre>
<p> 下面是实现count代码</p>
<pre name='code' class='java'>public static int getCount(String hql,Query query)
{
    // Count查询
if(!hql.startsWith("from"))
        {
    hql = hql.substring(hql.toLowerCase().indexOf(" from "));
    hql = "SELECT COUNT(*) " +hql;           
        }
//这里得不到页面传进来值?难道我还要去写query.setString()....      
   query=getSession().createQuery(hql);
   int count=((Integer)query.iterate().next()).intValue();
return  count;
}</pre>
<p> </p>
11 楼 myprincejava 2008-07-26  
请问icewubin
  你里面那个 HqlUtils是写一个方法还是?我导入包没有这个?谢谢能告知....
10 楼 myprincejava 2008-07-26  
icewubin 写道
同时提醒,楼主的第一和第三种方法几乎是无法用在生产环境的,性能太差了,是绝对要避免出现的。

除非记录数在100以下,但是一般都会使用通用接口,所以即使适用小数据量也是没有太大的实际开发意义。

谢谢你的回复哈!我按照你的方法先试试!不错...不是不能用select count(*) from 只是没有找到最好方法实现!
要想实现得到count总记录数可能只有用这个....主要是公用接口!
9 楼 icewubin 2008-07-25  
同时提醒,楼主的第一和第三种方法几乎是无法用在生产环境的,性能太差了,是绝对要避免出现的。

除非记录数在100以下,但是一般都会使用通用接口,所以即使适用小数据量也是没有太大的实际开发意义。
8 楼 icewubin 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);
}

7 楼 movingboy 2008-07-25  
我觉得老老实实用select count(*) from ...就好了,但你已经说不能这样用,我就没办法了
6 楼 bottom 2008-07-25  
如果是动态查询,总数是变动的,无法缓存。

暂无办法,唯有数据库 performance tuning or query tuning。
5 楼 sunmonve 2008-07-25  
建议总数可以缓存一下
4 楼 spiritfrog 2008-07-25  
lz用的什么数据库?又是什么驱动?
看看http://www.iteye.com/topic/9881?page=1
除了count(*),还可以用服务器端游标的,不过跟数据库驱动实现有关
3 楼 myprincejava 2008-07-25  
myprincejava 写道
movingboy 27 分钟前
是分页有性能问题,还是取总记录数有性能问题?有没有试过用Query的setFirstResult和setMaxResults方法来实现分页?
  

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

2 楼 myprincejava 2008-07-25  
movingboy 27 分钟前
是分页有性能问题,还是取总记录数有性能问题?有没有试过用Query的setFirstResult和setMaxResults方法来实现分页?

是取总记录数有性能问题哈?我就是用Query的setFirstResult和setMaxResults方法来实现分页?又没什么好方法来实现得到count总记录数!
  谢谢!
1 楼 movingboy 2008-07-25  
是分页有性能问题,还是取总记录数有性能问题?有没有试过用Query的setFirstResult和setMaxResults方法来实现分页?

相关推荐

    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