Java 简单的hibernate查询返回速度非常慢
我有以下hibernate查询:Java 简单的hibernate查询返回速度非常慢,java,hibernate,objectinstantiation,Java,Hibernate,Objectinstantiation,我有以下hibernate查询: Query query = session.createQuery("from MyHibernateClass"); List<MyHibernateClass> result = query.list();// executes in 7000ms 在MyHibernateClass数据库表中3500行的小数据集上测量jvm中的java代码时,大约需要7000ms 另一方面,如果我使用直接jdbc,如下所示: Statement stateme
Query query = session.createQuery("from MyHibernateClass");
List<MyHibernateClass> result = query.list();// executes in 7000ms
在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
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
然后是以下日志语句中的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在做什么?我怎么知道呢?如果您在应用程序中使用Log4j,您可以针对Hibernate设置各种不同的日志选项,以便更好地了解Hibernate的幕后情况
我猜这是在应用程序中首次调用HQL查询时发生的典型初始加载时间。在第一次查询之后,后续的HQL查询应该会显著加快。基于新的信息,我觉得我应该提供另一个答案。不同之处在于,您在bean中为列表或集合属性指定了一对多关联 您可能正在指定将关闭延迟加载的
lazy=false
。在禁用延迟加载的情况下,它将获取每个MyHibernateClass
实体的所有关联记录,这就是为什么它要花这么长时间执行
尝试设置
lazy=true
,这将执行得更快,然后仅在从实体显式请求关联实体时检索它们。添加一个具有类的所有属性的构造函数就成功了,现在hibernate查询的执行时间是70毫秒。以前,这个类只有一个没有参数的默认构造函数和一个带有实体id参数的构造函数。我知道这个线程很旧,但是为了更新,我遇到了同样的问题,但是使用SQL Server,结果是Hibernate打印的SQL和使用驱动程序发送的SQL是不同的。默认情况下,使用MSSQL驱动程序会将查询作为存储过程发送给RPC调用,这是因为驱动程序尝试优化MSSQL标准的查询计划,所以它会发送类似以下内容的查询
休眠查询:
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
实际驱动程序发送查询:
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优化往往会产生良好的缓存查询计划,但这会导致“参数嗅探”,以便了解更多有关此问题的信息,请阅读此处
因此,为了克服这一问题,我有以下选择:
Select * from customer c where c.name like **N**'somename' and c.country=**N**'somevalue'
这里的值前面有一个前缀,表示要转换编码方案,所以我禁用JDBCURL,使其为sendUnicode=false
这就是我在JTDS驱动程序选项中所做的一切。。就我而言,现在应用程序已经启动并运行得很快了。我还引入了二级缓存来缓存一段时间
希望这对某人有所帮助,如果你有任何好的建议,请让我知道。我知道这是一个老问题,但下面是为我解决它的方法 在您的hibernate.cfg.xml中,确保具有正确的!DOCTYPE。。。其内容应如下:
Statement statement = session.connection().createStatement();
ResultSet rs = statement.executeQuery("select * from MyHibernateClass");// 7ms
List<MyHibernateClass> result = convert(rs);// executes in 20ms
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
我遇到了一个事件,我的应用程序总是使用查询结果集中的每一行。通过使用下面的setFetchSize方法设置获取大小,我发现速度提高了40倍。(性能改进包括添加计数查询。)
做这件事时要小心;我的数据集大约有100行,它的范围是web请求生命周期中的一段时间。如果您有更大的数据集,则在将数据返回Java堆之前,您将在该数据存在的期间内吃掉Java堆。在我发现DOCTYPE标记在
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秒来执行任何查询。任何其他SQL Server遇到类似问题的人都可以在JDBC查询字符串中使用
sendStringParametersAsUnicode=false
,如以下回答所示:
如果准备语句参数不使用Unicode,并且希望利用
varchar
字段上的索引作为准备语句的参数,这可能会有所帮助。为什么您真的担心7ms?;)谢谢你提出一个澄清的问题。我更愿意使用hibernate版本,但7000毫秒的执行时间是不可接受的。我知道这个线程很旧,但为了更新,我遇到了相同的问题,但使用SQL Server,结果是hibernate打印的SQL和使用驱动程序发送的SQL是不同的。默认情况下,使用MSSQL驱动程序将查询作为存储过程作为RPC调用发送1。我添加了额外日志信息的输出,日志记录似乎会减慢系统的速度。2.在测试中的一个hql查询之前,我尝试执行另一个hql查询,但没有产生任何差异