论坛首页 Java企业应用论坛

Hibernate,JDBC性能探讨

浏览 11496 次
该帖已经被评为隐藏帖
作者 正文
   发表时间:2010-08-20   最后修改:2010-12-01

      今天原打算研究一下Hibernate 1+N问题,却发现了一个Really Amazing的效率问题,问题如下,希望大牛可以解释一下:

1、简单描述一下测试中表结构(我用Mysql数据库),表结构如下图



 表名为Corporation,三个字段id、name、type,对应Mysql中表结构截图:



 

2、如下代码,简单调运JDBC测试插入10000条数据花费时间

public class DB {
	public static Connection getConn() {
		Connection conn = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/hibernate?user=root&password=root");	
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
	public static Statement getStmt(Connection conn) {
		Statement stmt = null;
		try {
			if(conn != null) {
				stmt = conn.createStatement();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return stmt;
	}
	public static void main(String[] args) throws SQLException {
		Statement stmt = getStmt(getConn());
		Date start = new Date();
		for(int i = 0 ; i < 10000 ; i ++) {
			String sql = "insert into corporation(name,type) value('Tibco','IT')";
			stmt.executeUpdate(sql);
		}
		System.out.println("Total spent " + (new Date().getTime() - start.getTime()));
	}
}

 

运行时间如下

Total spent 249531

 这个时间我觉得是比较合理的执行一条SQL花费25毫秒左右,之前有关效率方面的测试和这个结果差不多

 

3. 下面给出Hibernate中测试时间的代码,先给出Hibernate配置代码

3.1 Corporation对应的Annotation配置类

@Entity
public class Corporation {
	private int id;
	private String name;
	private String type;
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
}

 3.2 hibernate.cfg.xml配置信息

<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/hibernate</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
		<property name="connection.pool_size">1</property>
		<property name="current_session_context_class">thread</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="hbm2ddl.auto">update</property>
        <mapping class="com.kylin.test.Corporation"/>
    </session-factory>
</hibernate-configuration>

 3.3给出测试代码

package com.kylin.test;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class AllTest {
	private static SessionFactory sessionFactory;
	@BeforeClass
	public static void beforeClass(){
		sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
	} 
	@AfterClass
	public static void afterClass() {
		sessionFactory.close();
	}
	@Test
	public void testExportTable() {
		new SchemaExport(new AnnotationConfiguration().configure()).create(true, true);
	}
	@Test
	public void saveCorporation() {
		Date start = new Date();
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		for(int i = 0 ; i < 10000 ; i ++) {
			Corporation c = new Corporation();
			c.setName("Tibco");
			c.setType("IT");
			session.save(c);
		}
		session.getTransaction().commit();
		System.out.println("Total spent " + (new Date().getTime() - start.getTime()));
	}
}

 

如上saveCorporation()方法就是Hibernate想数据库中插入10000条数据的部分,这个结果确实令我吃惊,如下

Total spent 8781

我测试了多次这个时间都是8700毫秒左右,所以这个时间应该准确。 

249531 / 8781 = 28.41,28倍,的确是28倍

4、分析一下

      之前比较过Cassandra(分布式数据库)与Mysql的存储效率差别时发现关系数据库存储的SQL操作效率相当低,而Hibernate解决的是可以面向对象的操作关系数据库,所以我个人一直以为,Hibernate操作数据库的效率一定更低,但结果却恰恰相反,而且与我的之前的理解相差很大,所以我可以肯定的是Hibernate在数据操作效率上也有一定的技巧,大家谁知道可以说说。

 

PS。。本来还想再分析分析,但是周末了,不想再多呆在公司……

  • 大小: 2.1 KB
  • 大小: 5.2 KB
   发表时间:2010-08-20  
估计hibernate是批量插入吧。看一下他执行的sql就明白了
0 请登录后投票
   发表时间:2010-08-20  
batch啊batch
jdbc改成batch试试
0 请登录后投票
   发表时间:2010-08-20  
出了batch 以外

jdbc 插入的代码写也有问题。

你那个写法, 每个insert 都要启动和提交一个事务

调用 conn.startTranscation()
然后在执行 insert
最后 conn.commit()

改成这样, jdbc 估计就比hibernate 快10倍了
1 请登录后投票
   发表时间:2010-08-21  
hibernate不可能比jdbc快的。
如楼上几位所言:

1、batch
2、事务
3、PreparedStatement
4、String sql往外放(这个影响较小)
1 请登录后投票
   发表时间:2010-08-21  
hibernate跑起来不可能比Mysql快的。应该是楼主的jdbc插入有问题。或者是hibernate默认的是批量插入。应该看下他的代码就知道了。
0 请登录后投票
   发表时间:2010-08-21  
呵呵,一叶障目不见泰山!
0 请登录后投票
   发表时间:2010-08-21  
要看你组织的SQL了, Hibernate无论如何 也没有SQL快,呵呵呵,  至少它要浪费一步时间去生成SQL,然后再交给DB,呵呵呵呵
0 请登录后投票
   发表时间:2010-08-21  
JDBC 1秒 1万条简单sql是没有问题

你batch 10000
0 请登录后投票
   发表时间:2010-08-21   最后修改:2010-08-21
hibernate 底层就是Jdbc 她不可能超越JDBC

只是hibernate漠然有优化  如果你的HDBC很垃圾 那自然hibernate快

如果都是最优那JDBC原始肯定快

但是要求程序员高
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics