简单的hibernate查询返回非常缓慢

我有以下的hibernate查询:

Query query = session.createQuery("from MyHibernateClass"); List<MyHibernateClass> result = query.list();// executes in 7000ms 

logging在MySQL中执行的SQL我看到

 select myhibernat0_.myFirstColumn as myfirstcolumn92_, myhibernat0_.mySecondColumn as mysecondcolumn92_, myhibernat0_.mythirdcolumn as mythirdcolumn92_, myhibernat0_.myFourthColumn as myfourthcolumn92_ from MyHibernateClass myhibernat0_ where (1=1); 

当在MyHibernateClass数据库表中的3500行的小数据集中测量jvm中的java代码时,大约需要7000ms。

如果我另一方面使用直接jdbc,如下所示:

 Statement statement = session.connection().createStatement(); ResultSet rs = statement.executeQuery("select * from MyHibernateClass");// 7ms List<MyHibernateClass> result = convert(rs);// executes in 20ms 

我看到相同的数据库进入数据库,但现在花费在jvm中的java代码的时间是7ms。

MyHibernateClass是一个简单的带有getter和setter的java bean类,我没有使用特殊的resulttransformers,如示例中所示。 我只需要一个类的只读实例,它不需要连接到hibernate会话。

我宁愿使用hibernate版本,但不能接受执行时间。

添加的信息 :添加hibernate日志后,我看到

 [2011-07-07 14:26:26,643]DEBUG [main] [logid: ] - org.hibernate.jdbc.AbstractBatcher.logOpenResults(AbstractBatcher.java:426) - about to open ResultSet (open ResultSets: 0, globally: 0) 

其次是3500个以下的日志语句

 [2011-07-07 14:26:26,649]DEBUG [main] [logid: ] - org.hibernate.loader.Loader.getRow(Loader.java:1197) - result row: EntityKey[com.mycom.MyHibernateClass#1] 

其次是3500个日志语句

 [2011-07-07 14:27:06,789]DEBUG [main] [logid: ] - org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:130) - resolving associations for [com.mycom.MyHibernateClass#1] [2011-07-07 14:27:06,792]DEBUG [main] [logid: ] - org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:226) - done materializing entity [com.mycom.MyHibernateClass#1] 

这是什么意思?

Hibernate在第一次执行时做了什么,我怎么知道?

添加一个具有类的所有属性的构造函数的窍门,现在的执行时间为70毫秒hibernate查询。 以前这个类只有一个没有参数的默认构造函数和一个带有实体id参数的构造函数。

基于新的信息,我觉得我应该提供另一个答案。 差异看起来像是在bean中为List或Set属性指定了一对多关联。

您可能指定了lazy=false ,这将closures延迟加载。 closures延迟加载它将获取每个MyHibernateClass实体的每个关联logging,这就是为什么它需要这么长的时间来执行。

尝试设置lazy=true ,这将执行得更快,然后只从实体明确请求时才检索关联的实体。

如果在应用程序中使用Log4j,则可以设置Hibernate特有的各种不同的日志logging选项,以便更好地了解Hibernate中幕后的情况。

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/session-configuration.html#configuration-logging

我的猜测是,这是在应用程序中首次调用HQL查询时发生的典型初始加载时间。 在第一次之后,后续的HQL查询应该明显快得多。

我知道这个线程是旧的,但更新我遇到了同样的问题,但与SQL Server,事实certificate,由Hibernate和SQL使用驱动程序发送的SQL是不同的。 默认情况下使用MSSQL驱动程序将查询作为RPC调用的存储过程发送,这是因为驱动程序试图优化MSSQL Standards的查询计划,所以它发送查询

hibernate查询:

 select c.col1,c.col2 from customer c where c.name like @param1 and c.country like @param2 

实际的驱动程序发送查询:

 @param1=somevalue, @param2=somevalue declar sp .... select c.col1,c.col2 from customer c where c.name like @param1 and c.country like @param2 go 

注意:这个查询我通过SQL Profiler工具直接在数据库上侦听

事实certificate,MSSQL上的sp_exec优化倾向于产生被caching的好的查询计划,但是这会导致“参数嗅探”来更多地了解这个问题。

所以为了克服这个,我有以下select:

  1. 将我的HQL更改为本地查询并为某些参数添加选项重新指定

  2. 使用直接查询值而不是准备好的语句,所以参数值将不会被翻译,查询也不会被驱动程序修改为存储过程

  3. 更改驱动程序设置为不发送存储过程(这仍然是坏的,因为现在MSSQL服务器中的查询计划将特定于此查询,这与Option:2相同,但在代码之外)

我不想使用OPTION 1和2,因为这消除了使用ORM框架的全部目的,现在我终于使用OPTION 3

所以我改变了JDBC URL来发送选项prepareStatement = false

设置后,我有一个问题的查询被发送像

  Select * from customer c where c.name like **N**'somename' and c.country=**N**'somevalue' 

这里有一个前缀的值,表示要转换的编码scheme,所以我禁用JDBC url sendUnicode = false

这一切我在JTDS驱动程序的选项..就我而言,现在的应用程序运行快速。 我还引入了二级caching来caching一段时间。

希望这有助于某人,如果你有任何好的build议,请让我知道。

我知道这是一个古老的问题,但这里是固定的我…

在你的hibernate.cfg.xml中,确保你有正确的!DOCTYPE …应该如下:

 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 

我有一个事件,我的应用程序总是使用查询的结果集中的每一行。 通过使用下面的setFetchSize方法设置我的读取大小,我发现速度提高了40倍。 (性能改进包括添加计数查询。)

  Long count = getStoreCount(customerId); Query query = session.getNamedQuery("hqlGetStoresByCustomerId") .setString("i_customerid",customerId) .setFetchSize(count.intValue()); 

这样做时要小心; 我的数据集有大约100行,它的范围是一个Web请求的生命周期。 如果你有更大的数据集,那么在返回到Java Heap之前,你将在这个数据的存在期间吃掉Java Heap。

在我发现DOCTYPE标签写在hibernate.cfg.xml*mapping object*.hbm.class之前,我花了10秒钟来执行一个简单的select所有查询

确保hibernate.cfg.xml

 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 

和映射xml.class

 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

现在花了我1-2秒来执行任何查询。