我有以下hibernate查询:
Query query = session.createQuery("from MyHibernateClass");
List<MyHibernateClass> result = query.list();// executes in 7000ms
当记录在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
我看到相同的sql进入数据库,但现在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在第一次实现中做了什么,我该如何找到?
答案 0 :(得分:28)
添加具有该类的所有属性的构造函数就可以了,现在hibernate查询的执行时间是70ms。以前,该类只有一个没有参数的默认构造函数和一个带有实体id参数的构造函数。
答案 1 :(得分:6)
根据新信息,我觉得我应该提供另一个答案。区别似乎是您为bean中的List或Set属性指定了一对多关联。
您可能正在指定lazy=false
将关闭延迟加载。关闭延迟加载后,它将获取每个MyHibernateClass
实体的每个相关记录,这就是执行这么长时间的原因。
尝试设置lazy=true
,这样可以更快地执行,然后只在从实体明确请求时检索关联的实体。
答案 2 :(得分:4)
如果您在应用程序中使用Log4j,您可以设置特定于Hibernate的各种不同的日志记录选项,以更好地了解Hibernate中幕后发生的事情。
我的猜测是,这是在应用程序中首次调用HQL查询时发生的典型初始加载时间。在第一次HQL查询之后,后续的HQL查询应该明显加快。
答案 3 :(得分:4)
我知道这个线程已经老了,但要更新我遇到了同样的问题,但是使用SQL Server,结果证明是由Hibernate打印的SQL和使用驱动程序发送的SQL是不同的。默认情况下使用MSSQL驱动程序将查询作为存储过程发送为RPC调用它,因为驱动程序尝试优化MSSQL标准的查询计划,因此它会发送类似
的查询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工具直接侦听DB
事实证明,MSSQL上的sp_exec优化往往会产生很好的查询计划,但这会导致“参数嗅探”以了解更多有关此处读取此问题的信息......
为了克服这个问题,我有以下选择:
将我的HQL更改为本机查询并为某些参数添加OPTION RECOMPILE
使用直接查询值而不是预准备语句,因此不会对参数值进行转换,并且驱动程序不会将查询修改为存储过程
更改驱动程序设置以不发送存储过程(这仍然很糟糕,因为现在MSSQL服务器中的查询计划将特定于此查询,这与选项:2相同但在代码之外)
我不想使用OPTION 1&amp; 2因为这样就消除了使用ORM框架的整个目的,我现在最终使用OPTION 3
所以我将JDBC URL更改为发送选项prepareStatement = false
设置完成后,我还有一个问题就是像
一样发送查询 Select * from customer c where c.name like **N**'somename' and c.country=**N**'somevalue'
这里有一个前缀,表示要转换编码方案的值,所以我禁用JDBC url sendUnicode = false
这就是我在JTDS驱动程序选项中所做的一切..就我现在所关注的而言,应用程序启动并运行得很快。我还引入了二级缓存来缓存它一段时间..
希望这对某人有帮助,如果您有任何好的建议请告诉我。
答案 4 :(得分:1)
我知道这是一个古老的问题,但这就是为我解决的问题......
在你的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">
答案 5 :(得分:1)
我遇到了一个事件,我的应用程序总是使用查询结果集中的每一行。通过使用下面的setFetchSize方法设置我的提取大小,我发现速度提高了40倍。 (性能改进包括添加计数查询。)
Long count = getStoreCount(customerId);
Query query = session.getNamedQuery("hqlGetStoresByCustomerId")
.setString("i_customerid",customerId)
.setFetchSize(count.intValue());
这样做时要小心;我的数据集大约有100行,它的范围是Web请求的生命周期。如果您有更大的数据集,那么在将数据返回到Java堆之前,您将在存在该数据期间使用Java堆。
答案 6 :(得分:1)
面对SQL Server类似问题的任何人都可以在JDBC查询字符串中使用sendStringParametersAsUnicode=false
,如下所示:
JPA (Hibernate) Native Query for Prepared Statement SLOW
如果您没有将Unicode用于准备好的语句参数,并且想利用varchar
字段上的索引作为准备好的语句的参数,这会有所帮助。
答案 7 :(得分:-1)
在我发现在hibernate.cfg.xml
和*mapping object*.hbm.class
确保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秒执行任何查询。