`

Hibernate使用自定义主键生成器@TableGenerator和数据库自身生成器的性能测试

 
阅读更多
Hibernate提供实现类:org.hibernate.id.MultipleHiLoPerTableGenerator
碰到一个问题:
org.hibernate.id.IdentifierGeneratorHelper类里面的方法:
value:当前值,
factor:model类定义的allocationSize = 100小1,及时99(第一次传入的信息)
public IntegralDataTypeHolder multiplyBy(long factor) {
			checkInitialized();
			value *= factor;
			return this;
		}
,从这里可以看到启动服务器的时候第一次执行到这里,就发现表的主键是tb_generator(保存主键信息)表的gen_value的allocationSize倍数。那么会浪费掉很多主键值。
上面的方法被org.hibernate.id.enhanced.OptimizerFactory的public synchronized Serializable generate()调用,maxLo同时初始化这个变量,这个变量maxLo+1就是factor。




hibernate中自定义主键生成器:http://panyongzheng.iteye.com/blog/1827786
探索 Hibernate 新 TableGenerator 机制 http://www.ibm.com/developerworks/cn/java/j-lo-tablegenerator/index.html?ca=drs-
探索 Hibernate 新 TableGenerator 机制 http://www.itpub.net/thread-1822509-1-1.html

Hibernate的主键生成策略与并发测试http://blog.sina.com.cn/s/blog_56d8ea900100xb8h.html
一些重要的知识,可以在这里看到.

SpringMVC3.x, Hiberante4, sql server 2008, 数据库的VM内存2G, 本机的web环境内存8G(VM在本机上建立的), j2ee环境option内存:1G.  服务器:jetty,  idea采用非调试启动.
这里不想讨论为什么使用@TableGenerator, 因为没必要,只是比较性能而已.

在运行是, 没有手动session.flush()等操作.

使用自定义主键生成器的service
pojo的主键定义示例:
@GeneratedValue(strategy = GenerationType.TABLE,generator="customer_gen")
    @TableGenerator(name = "customer_gen",
            table="tb_generator",
            pkColumnName="gen_name",
            valueColumnName="gen_value",
            pkColumnValue="testtable_PK"
    )

注意,没有设定allocationSize属性,默认是50.
@Override
    public void saveTestData(int sum) {
        /*
        DELETE FROM dbo.testtable3;
        DELETE FROM dbo.testtable2;
        DELETE FROM dbo.testtable1;
        DELETE FROM dbo.testtable;
         */
        Date d1 = new Date();
        //单表
        for(int i=0; i<sum; i++){
            Testtable t = new Testtable();
            t.setCode("Test"+i);
            testtableDao.save(t);
            //System.out.println("自定义主键生成 记录:"+i+" 单表:"+(new Date()).toString());
        }
        System.out.println("完成单表操作");


        //关联
        for(int i=0; i<sum; i++){
            Testtable1 p = new Testtable1();
            p.setCode("P"+i);
            p = testtable1Dao.save(p);

            Testtable2 c = new Testtable2();
            c.setTesttable1(p);
            c.setCode("C"+i);
            testtable2Dao.save(c);
            //System.out.println("自定义主键生成 记录:"+i+" 关联:"+(new Date()).toString());
        }
        System.out.println("完成关联操作");

        //映射
        for(int i=0;i<sum; i++){
            Testtable t = new Testtable();
            t.setCode("T"+i);
            t =  testtableDao.save(t);

            Testtable2 c = new Testtable2();
            c.setCode("C"+i);
            c = testtable2Dao.save(c);

            Testtable3 m = new Testtable3();
            m.setCode("M"+i);
            m.setTesttable(t);
            m.setTesttable2(c);
            m = testtable3Dao.save(m);
            //System.out.println("自定义主键生成 记录:"+i+" 映射:"+(new Date()).toString());
        }
        System.out.println("完成映射操作");
        System.out.println("Over......");
        Date d2 = new Date();
        long t = d2.getTime() - d1.getTime();
        System.out.println("service耗时=" + (t / 1000) + "s");

    }


使用数据库自己的主键生成器的service
pojo的主键定义示例:
@GeneratedValue(strategy = GenerationType.AUTO)

@Override
    public void saveTestData(int sum) {
        /*
        DELETE FROM dbo.atabletest3;
        DELETE FROM dbo.atabletest2;
        DELETE FROM dbo.atabletest1;
        DELETE FROM dbo.atabletest;
         */
        Date d1 = new Date();
        //单表
        for(int i=0; i<sum; i++){
            Atabletest t = new Atabletest();
            t.setCode("Test"+i);
            atabletestDao.save(t);
            //System.out.println("数据库主键生成 记录:"+i+" 单表:"+(new Date()).toString());
        }
        System.out.println("完成单表操作");



        //关联
        for(int i=0; i<sum; i++){
            Atabletest1 p = new Atabletest1();
            p.setCode("P"+i);
            p = atabletest1Dao.save(p);

            Atabletest2 c = new Atabletest2();
            c.setAtabletest1(p);
            c.setCode("C"+i);
            atabletest2Dao.save(c);
            //System.out.println("数据库主键生成 记录:"+i+" 关联:"+(new Date()).toString());
        }
        System.out.println("完成关联操作");


        //映射
        for(int i=0;i<sum; i++){
            Atabletest t = new Atabletest();
            t.setCode("T"+i);
            t =  atabletestDao.save(t);

            Atabletest2 c = new Atabletest2();
            c.setCode("C"+i);
            c = atabletest2Dao.save(c);

            Atabletest3 m = new Atabletest3();
            m.setAtabletest(t);
            m.setAtabletest2(c);
            m.setCode("M"+i);
            m = atabletest3Dao.save(m);
            //System.out.println("数据库主键生成 记录:"+i+" 映射:"+(new Date()).toString());
        }
        System.out.println("完成映射操作");
        System.out.println("Over......");
        Date d2 = new Date();
        long t = d2.getTime() - d1.getTime();
        System.out.println("service耗时=" + (t / 1000) + "s");
    }



调用service的controller方法
@RequestMapping("/test")
    public ModelAndView test(@RequestParam("flag") int flag, @RequestParam("sum") int sum) {
        if (flag == 1) {
            Date d1 = new Date();
            testtableManager.saveTestData(sum);
            Date d2 = new Date();

            long t = d2.getTime() - d1.getTime();
            System.out.println("使用自定义主键生成器");
            System.out.println("记录数:"+(sum*6)+" 耗时=" + (t / 1000) + "s");
        } else if (flag == 0) {
            Date d1 = new Date();
            atabletestManager.saveTestData(sum);
            Date d2 = new Date();

            long t = d2.getTime() - d1.getTime();
            System.out.println("使用数据库主键生成器");
            System.out.println("记录数:"+(sum*6)+" 耗时=" + (t / 1000) + "s");
        } else {

        }

        return null;
    }



测试结果:
10万级别的,自定义要快一点, .
1万级别的,数据库自己的主键要快一点, .
1000条级别的,自定义要快一点 .

60w条数据:
使用自定义主键生成器:
service耗时=142s 耗时=1195s, service耗时=130s 耗时=1587s
使用数据库主键生成器
service耗时=974s 耗时=1284s, service耗时=971s 耗时=1662s

6w条数据:
使用自定义主键生成器:
service耗时=13s 耗时=94s, service耗时=12s 耗时=92s, service耗时=12s 耗时=104s
使用数据库主键生成器
service耗时=89s 耗时=92s, service耗时=82s 耗时=85s, service耗时=90s 耗时=93s

6000条数据:
使用自定义主键生成器:
service耗时=1s 耗时=10s, service耗时=1s 耗时=10s, service耗时=1s 耗时=11s
使用数据库主键生成器
service耗时=9s 耗时=10s, service耗时=10s 耗时=12s, service耗时=8s 耗时=10s
分享到:
评论

相关推荐

    表生成器 @TableGenerator

    NULL 博文链接:https://mqyl1.iteye.com/blog/1098358

    Hibernate注释大全收藏

    一旦使用就不能使用AUTO和IDENTIFY生成器。 每个类层次结构一张表 @Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="planetype", discriminatorType=...

    JPA-2 基本注解

    JPA的基本注解主要包括@Entity、@Table、@Id、@GeneratedValue、@Basic、@Column、@Transient、@Temporal和@TableGenerator等。

    JPA 标注 JPA标签手册

    这是JPA标签配置手册,从ORACLE官方得到的资料,里面对JPA所有的标签都进行详细的说明。 Index of Annotations ...o @TableGenerator o @Temporal o @Transient • U o @UniqueConstraint • V o @Version

    JPA学习笔记(二)——JPA 注解

    JPA注解1.1 @Entity1.2 @Table1.3 @Id1.4 @GeneratedValue1.5 @Basic1.6 @Column1.7 @Transient1.8 @Temporal1.9 @TableGenerator 1. JPA注解 1.1 @Entity 标注在实体类上,表示此类对应一个数据表。 1.2 @Table 与...

    编程狂人第十二期

    探索 Hibernate 新 TableGenerator 机制 服务好“最后一公里”,高效CDN架构经验 探索推荐引擎内部的秘密 一起 select 引起的崩溃 课堂上传纸条如何防范中间人攻击? 程序人生 《9Tech访谈录》揭秘游戏王子白泽的...

    table-generator:Sublime Text 3插件,用于将类似CSV的文本转换为其他可读表格式

    表格生成器-ST3插件甲崇高文本3插件用于将CSV状文本到其它可读表格格式在适当位置。 转换器内部的功劳 。 演示:安装将存储库克隆到Sublime Text“ Packages”目录中: git clone ...

    javax.persistence.jar

    javax.persistence.TableGenerator.class javax.persistence.Temporal.class javax.persistence.TemporalType.class javax.persistence.TransactionRequiredException.class javax.persistence.Transient.class ...

Global site tag (gtag.js) - Google Analytics