知识大全 hibernate大数据性能处理
Posted 知
篇首语:不要为成功而努力,要为作一个有价值的人而努力。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 hibernate大数据性能处理相关的知识,希望对你有一定的参考价值。
在项目中使用Hibernate进行大数据量的性能测试 有一些总结 ) 在处理大数据量时 会有大量的数据缓冲保存在Session的一级缓存中 这缓存大太时会严重显示性能 所以在使用Hibernate处理大数据量的 可以使用session clear()或者session Evict(Object) 在处理过程中 清除全部的缓存或者清除某个对象 ) 对大数据量查询时 慎用list()或者iterator()返回查询结果 使用List()返回结果时 Hibernate会所有查询结果初始化为持久化对象 结果集较大时 会占用很多的处理时间 而使用iterator()返回结果时 在每次调用iterator next()返回对象并使用对象时 Hibernate才调用查询将对应的对象初始化 对于大数据量时 每调用一次查询都会花费较多的时间 当结果集较大 但是含有较大量相同的数据 或者结果集不是全部都会使用时 使用iterator()才有优势 对于大数据量 使用qry scroll()可以得到较好的处理速度以及性能 而且直接对结果集向前向后滚动 ) 对于关联操作 Hibernate虽然可以表达复杂的数据关系 但请慎用 使数据关系较为简单时会得到较好的效率 特别是较深层次的关联时 性能会很差 ) 对含有关联的PO(持久化对象)时 若default cascade= all 或者 save update 新增PO时 请注意对PO中的集合的赋值操作 因为有可能使得多执行一次update操作 ) 在一对多 多对一的关系中 使用延迟加载机制 会使不少的对象在使用时方会初始化 这样可使得节省内存空间以及减少的负荷 而且若PO中的集合没有被使用时 就可减少互数据库的交互从而减少处理时间 数据库 什么叫n+ 次select查询问题? 在Session的缓存中存放的是相互关联的对象图 默认情况下 当Hibernate从数据库中加载Customer对象时 会同时加载所有关联的Order对象 以Customer和Order类为例 假定ORDERS表的CUSTOMER_ID外键允许为null 图 列出了CUSTOMERS表和ORDERS表中的记录 以下Session的find()方法用于到数据库中检索所有的Customer对象 List customerLists=session find( from Customer as c ) 运行以上find()方法时 Hibernate将先查询CUSTOMERS表中所有的记录 然后根据每条记录的ID 到ORDERS表中查询有参照关系的记录 Hibernate将依次执行以下select语句 select * from CUSTOMERS; select * from ORDERS where CUSTOMER_ID= ; select * from ORDERS where CUSTOMER_ID= ; select * from ORDERS where CUSTOMER_ID= ; select * from ORDERS where CUSTOMER_ID= ; 通过以上 条select语句 Hibernate最后加载了 个Customer对象和 个Order对象 在内存中形成了一幅关联的对象图 参见图 Hibernate在检索与Customer关联的Order对象时 使用了默认的立即检索策略 这种检索策略存在两大不足 (a) select语句的数目太多 需要频繁的访问数据库 会影响检索性能 如果需要查询n个Customer对象 那么必须执行n+ 次select查询语句 这就是经典的n+ 次select查询问题 这种检索策略没有利用SQL的连接查询功能 例如以上 条select语句完全可以通过以下 条select语句来完成 select * from CUSTOMERS left outer join ORDERS on CUSTOMERS ID=ORDERS CUSTOMER_ID 以上select语句使用了SQL的左外连接查询功能 能够在一条select语句中查询出CUSTOMERS表的所有记录 以及匹配的ORDERS表的记录 (b)在应用逻辑只需要访问Customer对象 而不需要访问Order对象的场合 加载Order对象完全是多余的操作 这些多余的Order对象白白浪费了许多内存空间 为了解决以上问题 Hibernate提供了其他两种检索策略 延迟检索策略和迫切左外连接检索策略 延迟检索策略能避免多余加载应用程序不需要访问的关联对象 迫切左外连接检索策略则充分利用了SQL的外连接查询功能 能够减少select语句的数目 刚查阅了hibernate 的文档 查询抓取(默认的)在N+ 查询的情况下是极其脆弱的 因此我们可能会要求在映射文档中定义使用连接抓取 <set name= permissions fetch= join > <key column= userId /> <one to many class= Permission /> </set <many to one name= mother class= Cat fetch= join /> 在映射文档中定义的抓取策略将会有产生以下影响 通过get()或load()方法取得数据 只有在关联之间进行导航时 才会隐式的取得数据(延迟抓取) 条件查询 在映射文档中显式的声明 连接抓取做为抓取策略并不会影响到随后的HQL查询 通常情况下 我们并不使用映射文档进行抓取策略的定制 更多的是 保持其默认值 然后在特定的事务中 使用HQL的左连接抓取(left join fetch) 对其进行重载 这将通知 Hibernate在第一次查询中使用外部关联(outer join) 直接得到其关联数据 在条件查询 API中 应该调用 setFetchMode(FetchMode JOIN)语句 ) 对于大数据量新增 修改 删除操作或者是对大数据量的查询 与数据库的交互次数是决定处理时间的最重要因素 减少交互的次数是提升效率的最好途径 所以在开发过程中 请将show_sql设置为true 深入了解Hibernate的处理过程 尝试不同的方式 可以使得效率提升 ) Hibernate是以JDBC为基础 但是Hibernate是对JDBC的优化 其中使用Hibernate的缓冲机制会使性能提升 如使用二级缓存以及查询缓存 若命中率较高明 性能会是到大幅提升 ) Hibernate可以通过设置hibernate jdbc fetch_size hibernate jdbc batch_size等属性 对Hibernate进行优化 hibernate jdbc fetch_size hibernate jdbc batch_size 这两个选项非常非常非常重要!!!将严重影响Hibernate的CRUD性能! C = create R = read U = update D = delete Fetch Size 是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数 例如一次查询 万条记录 对于Oracle的JDBC驱动来说 是不会 次性把 万条取出来的 而只会取出Fetch Size条数 当纪录集遍历完了这些记录以后 再去数据库取Fetch Size条数据 因此大大节省了无谓的内存消耗 当然Fetch Size设的越大 读数据库的次数越少 速度越快 Fetch Size越小 读数据库的次数越多 速度越慢 这有点像平时我们写程序写硬盘文件一样 设立一个Buffer 每次写入Buffer 等Buffer满了以后 一次写入硬盘 道理相同 Oracle数据库的JDBC驱动默认的Fetch Size= 是一个非常保守的设定 根据我的测试 当Fetch Size= 的时候 性能会提升 倍之多 当Fetch Size= 性能还能继续提升 % Fetch Size继续增大 性能提升的就不显著了 因此我建议使用Oracle的一定要将Fetch Size设到 不过并不是所有的数据库都支持Fetch Size特性 例如MySQL就不支持 MySQL就像我上面说的那种最坏的情况 他总是一下就把 万条记录完全取出来 内存消耗会非常非常惊人!这个情况就没有什么好办法了 :( Batch Size是设定对数据库进行批量删除 批量更新和批量插入的时候的批次大小 有点相当于设置Buffer缓冲区大小的意思 Batch Size越大 批量操作的向数据库发送sql的次数越少 速度就越快 我做的一个测试结果是当Batch Size= 的时候 使用Hibernate对Oracle数据库删除 万条记录需要 秒 Batch Size = 的时候 删除仅仅需要 秒!!! // 我们通常不会直接操作一个对象的标识符(identifier) 因此标识符的setter方法应该被声明为私有的(private) 这样当一个对象被保存的时候 只有Hibernate可以为它分配标识符 你会发现Hibernate可以直接访问被声明为public private和protected等不同级别访问控制的方法(accessor method)和字段(field) 所以选择哪种方式来访问属性是完全取决于你 你可以使你的选择与你的程序设计相吻合 所有的持久类(persistent classes)都要求有无参的构造器(no argument constructor) 因为Hibernate必须要使用Java反射机制(Reflection)来实例化对象 构造器(constructor)的访问控制可以是私有的(private) 然而当生成运行时代理(runtime proxy)的时候将要求使用至少是package级别的访问控制 这样在没有字节码编入(bytecode instrumentation)的情况下 从持久化类里获取数据会更有效率一些 而 hibernate max_fetch_depth 设置外连接抓取树的最大深度 取值 建议设置为 到 之间 就是每次你在查询时 会级联查询的深度 譬如你对关联vo设置了eager的话 如果fetch_depth值太小的话 会发多很多条sql Hibernate的Reference之后 可以采用批量处理的方法 当插入的数据超过 时 就flush session并且clear 下面是一个测试method /** */ /** * 测试成批插入数据的事务处理 返回是否成功 * * @param objPO Object * @return boolean */ public boolean insertBatch( final Object objPO) boolean isSuccess = false ; Transaction transaction = null ; Session session = openSession() try transaction = session beginTransaction() for ( int i = ; i < ; i ++ ) session save(objPO) if (i % == ) // flush a batch of inserts and release memory session flush() session clear() mit() ( transaction wasCommitted: + transaction wasCommitted()) isSuccess = true ; catch (HibernateException ex) if (transaction != null ) try transaction rollback() logger error( transaction wasRolledBack: + transaction wasRolledBack()) catch (HibernateException ex ) logger error(ex getMessage()) ex printStackTrace() logger error( Insert Batch PO Error: + ex getMessage()) ex printStackTrace() finally if (transaction != null ) transaction = null ; session close() return isSuccess; 这只是简单的测试 实际项目中遇到的问题 要比这个复杂得多 这时候 我们可以让Spring来控制Transaction 自己来控制Hibernate的Session 随时更新数据 首先 利用HibernateDaoSupport类来自定义个方法打开Session public Session openSession() return getHibernateTemplate() getSessionFactory() openSession() 然后 用打开的Session处理你的数据 protected void doBusiness(Session session) while (true) //do your business with the opening session someMethod(session) session flush() session clear() ( good job! ) 每做一次数据操作 就更新一次Session 这样可以保证每次数据操作都成功 否则就让Spring去控制它roll back吧 最后 记得关闭Session Session session = openSession() doBusiness(session) session close() // 关闭session cha138/Article/program/Java/hx/201311/26054相关参考
文章出处 在一个拥有单独业务层的应用中业务层必须在返回之前为web层准备好其所需的数据集合这就意味着业务层应该载入所有表现层/web层所需的数据并将这些已实例化完毕的数据返回通常应用程序应该为w
Hibernate是对JDBC的轻量级封装因此在很多情况下Hibernate的性能比直接使用JDBC存取数据库要低然而通过正确的方法和策略在使用Hibernate的时候还是可以非常接近直接使用JD
Hibernate大数据量操作方案 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 阅读了Hibe
Hibernate在解决性能问题方面做得非常好有了它的缓存机制使用第三方缓存和数据库连接池就较好的解决的性能问题但这些还不够hibernate给了开发者足够的自由让开发者自己去控制性能问题 学习
浅析Hibernate下数据批量处理方法 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 很多人都
Spring+Hibernate处理大批量数据 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 对
Hibernate下数据批量处理解决方案 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 很多人都
为了进一步优化Hibernate的性能可以使用 延迟加载技术管理数据抓取策略进行缓存管理等方面考虑来提高Hibernate的性能 延迟加载(load) 延迟加载(load)是Hibernat
一批量修改和删除 在Hibernate中如果需要对任何数据进行修改和删除操作都需要先执行查询操作在得到要修改或者删除的数据后再对该数据进行相应的操作处理在数据量少的情况下采用这种处理方式没有问题
事务概述 事务就是指作为单个逻辑工作单元执行的一组数据操作这些操作要么必须全部成功要么必须全部失败以保证数据的一致性和完整性事务具有ACID属性 原子性自然界最小的事务的内容要么都做要么都不做