首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

batch_size 跟 fetch_size作用

2012-12-19 
batch_size 和 fetch_size作用hibernate抓取策略,,batch-szie在class上的应用batch-size属性,可以批量加

batch_size 和 fetch_size作用

hibernate抓取策略,,batch-szie在<class>上的应用

batch-size属性,可以批量加载实体类,

hbm.xml

classes.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
??? <class name="Classes" table="classes_join" batch-size="3">
??????? <id name="id" column="id" type="java.lang.Integer">
??????????? <generator />
??????? </id>
??????? <property name="name" column="name" type="java.lang.String" />
??????? <set name="students" >
??????????? <key column="class_id" />
??????????? <one-to-many />
??????? </set>
??? </class>

</hibernate-mapping>


Student.hbm.xml

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
??? <class name="Student" table="student_join" >
??????? <id name="id" column="id" type="java.lang.Integer">
??????????? <generator />?????????
??????? </id>
??????? <property name="name" column="name" length="50" type="java.lang.String" />
??????? <many-to-one name="classes" column="class_id" ></many-to-one>
??? </class>

</hibernate-mapping>

?

测试用例:
??? List stuList = session.createQuery("from Student s where s.id in (:ids)")
???????????????????????? .setParameterList("ids", new Object[]{1,10})
???????????????????????? .list();
??? for(Iterator it = stuList.iterator(); it.hasNext();){
???? Student stu = (Student)it.next();
???? System.out.println(stu.getName());
???? System.out.println(stu.getClasses().getName());
??? }

1)若没配batch-size,即<class name="Classes" table="classes_join">

执行结果:执行2条班级查询语句

Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.class_id as class3_1_ from student_join student0_ where student0_.id in (? , ?)
学生1
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes_join classes0_ where classes0_.id=?
高一(1)班
学生1
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes_join classes0_ where classes0_.id=?
高一(2)班

2)若配batch-size,即<class name="Classes" table="classes_join" batch-size="5">

执行结果:执行1条班级查询语句(每5个班级,发一条sql语句)

Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.class_id as class3_1_ from student_join student0_ where student0_.id in (? , ?)
学生1
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes_join classes0_ where classes0_.id in (?, ?)
高一(1)班
学生1
高一(2)班

?

===================================

hibernate抓取策略,batch-szie在集合上的应用


batch-size属性,可以批量加载实体类,
<set name="students" batch-size="5">??

hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
??? <class name="Classes" table="classes_join" >
??????? <id name="id" column="id" type="java.lang.Integer">
??????????? <generator />
??????? </id>
??????? <property name="name" column="name" type="java.lang.String" />
??????? <set name="students" batch-size="5" >
??????????? <key column="class_id" />
??????????? <one-to-many />
??????? </set>
??? </class>

</hibernate-mapping>

测试用例:

List classList = session.createQuery("from Classes").list();
??? for(Iterator iter = classList.iterator(); iter.hasNext();){
???? Classes c = (Classes)iter.next();
???? System.out.println("Class.name=" + c.getName());
???? Set stuSet = c.getStudents();
???? System.out.println(stuSet.size());
???? if(stuSet != null && !stuSet.isEmpty()){
????? for(Iterator it = stuSet.iterator(); it.hasNext();){
?????? Student s = (Student) it.next();
?????? System.out.println("student.name=" + s.getName());
????? }
???? }
??? }

加了 <set name="students" batch-size="5" > //每5条,做一次查询
如下:

Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id in (?, ?, ?, ?, ?)

Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id in (?, ?, ?, ?)

?

=================================

hibernate.jdbc.fetch_size 和 hibernate.jdbc.batch_size

hibernate.jdbc.fetch_size 50 //读

hibernate.jdbc.batch_size 30 //写

?

hiberante.cfg.xml(Oracle ,sql server 支持,mysql不支持)

?? <property name="hibernate.jdbc.fetch_size">50</property>
<property name="hibernate.jdbc.batch_size">30</property>

这两个选项非常非常非常重要!!!将严重影响Hibernate的CRUD性能!

?

C = create, R = read, U = update, D = delete

?

Fetch Size 是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数。

?

例如一次查询1万条记录,对于Oracle的JDBC驱动来说,是不会1次性把1万条取出来的,而只会取出Fetch Size条数,当纪录集遍历完了这些记录以后,再去数据库取Fetch Size条数据。

?

因此大大节省了无谓的内存消耗。当然Fetch Size设的越大,读数据库的次数越少,速度越快;Fetch Size越小,读数据库的次数越多,速度越慢。

?

这有点像平时我们写程序写硬盘文件一样,设立一个Buffer,每次写入Buffer,等Buffer满了以后,一次写入硬盘,道理相同。

?

Oracle数据库的JDBC驱动默认的Fetch Size=10,是一个非常保守的设定,根据我的测试,当Fetch Size=50的时候,性能会提升1倍之多,当Fetch Size=100,性能还能继续提升20%,Fetch Size继续增大,性能提升的就不显著了。

?

因此我建议使用Oracle的一定要将Fetch Size设到50

?

不过并不是所有的数据库都支持Fetch Size特性,例如MySQL就不支持。

?

MySQL就像我上面说的那种最坏的情况,他总是一下就把1万条记录完全取出来,内存消耗会非常非常惊人!这个情况就没有什么好办法了 :(

?

Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,有点相当于设置Buffer缓冲区大小的意思。

?

Batch Size越大,批量操作的向数据库发送sql的次数越少,速度就越快。我做的一个测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删除1万条记录需要25秒,Batch Size = 50的时候,删除仅仅需要5秒!!!

//
我们通常不会直接操作一个对象的标识符(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设置外连接抓取树的最大深度

取值. 建议设置为03之间

就是每次你在查询时,会级联查询的深度,譬如你对关联vo设置了eager的话,如果fetch_depth值太小的话,会发多很多条sql

?

http://apps.hi.baidu.com/share/detail/1229533

热点排行