• hibernate的速度问题--hibernate.jdbc.fetch_size和 hibernate.jdbc.batch_size


    hibernate的速度问题,这点我也疑惑过,最初应用hibernate的项目,我也感觉速度很慢,知道后来才知道问题的所在。 
          其实hibernate的速度性能并不差,比起jdbc来说,又是性能能高2倍。 
          当然了这和应用的数据库有关,在Oracle上,hibernate支持hibernate.jdbc.fetch_size和 hibernate.jdbc.batch_size,而MySQL却不支持,而我原来的项目绝大多数都是使用MySQL的,所以觉得速度慢,其实在企业级应用,尤其是金融系统大型应用上,使用Oracle比较多,相对来说,hibernate会提升系统很多性能的

    hibernate.jdbc.fetch_size 50

    hibernate.jdbc.batch_size 25

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

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

    1.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万条记录完全取出来,内存消耗会非常非常惊人!这个情况就没有什么好办法了 :(

    2.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

    batch-size可以设定在Hbm的class 和 集合定义中. 开始我一直以为batch-size是获取child的数量, 其实真正获取的是parent的数量.

    但是奇怪的是当我测试时  我把batch-size的值从1设置到5, 当设成1和2时其实每次获取的还是一个parent.当到3时就是同时获取3个parent.当多出select出来的parent时,感觉好像就没有规律了.我建议一般都把batch-size设成3

    下面的来自hibernate文档.(奇怪的是hibernate中文文档并没有关于 batch fetching 的介绍.)


    Hibernate can make efficient use of batch fetching, that is, Hibernate can load several uninitialized proxies if one proxy is accessed. Batch fetching is an optimization for the lazy loading strategy. There are two ways you can tune batch fetching: on the class and the collection level.

    Batch fetching for classes/entities is easier to understand. Imagine you have the following situation at runtime: You have 25 Cat instances loaded in a Session, each Cat has a reference to its owner, a Person. The Person class is mapped with a proxy, lazy="true". If you now iterate through all cats and call getOwner() on each, Hibernate will by default execute 25 SELECT statements, to retrieve the proxied owners. You can tune this behavior by specifying a batch-size in the mapping of Person:

    <class name="Person" lazy="true" batch-size="10">...</class>Hibernate will now execute only three queries, the pattern is 10, 10, 5. You can see that batch fetching is a blind guess, as far as performance optimization goes, it depends on the number of unitilized proxies in a particular Session.

    You may also enable batch fetching of collections. For example, if each Person has a lazy collection of Cats, and 10 persons are currently loaded in the Sesssion, iterating through all persons will generate 10 SELECTs, one for every call to getCats(). If you enable batch fetching for the cats collection in the mapping of Person, Hibernate can pre-fetch collections:

    <class name="Person">
        <set name="cats" lazy="true" batch-size="3">
            ...
        </set>
    </class>With a batch-size of 3, Hibernate will load 3, 3, 3, 1 collections in 4 SELECTs. Again, the value of the attribute depends on the expected number of uninitialized collections in a particular Session.

  • 相关阅读:
    eclipse 批量 查询 替换
    Hibernate包及相关工具包下载地址
    逻辑运算符&& 用法解释
    主流数据库查找前几条数据的区别
    .propertie文件注释
    java.io.EOFException java.io.ObjectInputStream$PeekInputStream.readFully 错误
    数据库的名称尽量要以英文开头,如果全部输数字的话可能会出错的
    **和*的区别
    puTTY与SecureCRT的比较
    Windows下Redis的安装使用
  • 原文地址:https://www.cnblogs.com/pingxin/p/p00031.html
Copyright © 2020-2023  润新知