首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Hibernate事务管理器性能问题

Hibernate事务管理器性能问题
EN

Stack Overflow用户
提问于 2015-10-13 16:57:47
回答 2查看 2.1K关注 0票数 3

目前,我在Hibernate中遇到了性能问题。

要执行SQL语句(例如select * from表),只需大约90 12就可以只获取10条包含12列的记录

但是,为了让hibernate在DAO类中运行以下java代码

代码语言:javascript
运行
复制
List<T> afterGetAll = getSessionFactory().getCurrentSession().createCriteria(type).list();

在执行上面的语句时,只执行大约需要260~300 ms,更不用说调用DAO的服务类中的额外执行时间了。总花费在600~1000 ms左右。我怀疑大部分时间都花在事务管理上。

我不知道我的代码/配置哪里出错了,我也尝试过以下方法,但是没有太大帮助.

  1. 在dataSource设置中添加连接池
  2. 在DAO类中使用hibernate原生SQL方法代替createCriteria
  3. 启用延迟负载
  4. 增加tomcat服务器的堆大小
  5. 使用二级缓存提供程序
  6. @Transactional(readOnly = true)用于只读查询

加速操作的一些解决办法:

  1. 通过配置EhCacheRegionFactory来启用hibernate缓存,并一起启用二级缓存。然后,在服务器开始时,我的web应用程序通过手动触发服务调用来初始化缓存。这可以成功地将Hibernate获取sql查询后的数据绑定过程从300~400 3ms减少到1~3ms。但是,瓶颈在提交事务时.(请参阅下面的Update#2 )

这是我的配置和代码

Hibernate配置

代码语言:javascript
运行
复制
<bean id="jdbcTemplate" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver" />
    <property name="jdbcUrl" value="jdbc:mysql://test />
    <property name="user" value="test" />
    <property name="password" value="test" />
    <property name="maxPoolSize" value="20" />
    <property name="minPoolSize" value="5" />
    <property name="maxStatements" value="5" />
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="jdbcTemplate"></property>
    <property name="mappingResources">
        <list>
            <value>orm/UserModel.hbm.xml</value>
            <value>orm/UserToken.hbm.xml</value>
            <value>orm/RoleModel.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
        <prop key="hibernate.use_sql_comments">true</prop>
        <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
        <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>  
        <prop key="hibernate.cache.use_second_level_cache">true</prop>   
        <prop key="hibernate.c3p0.minPoolSize">5</prop>
        <prop key="hibernate.c3p0.maxPoolSize">20</prop>
      </props>
    </property>
</bean>

<bean id="baseDao" abstract="true" class="com.test.app.project.dao.BaseDAOImpl">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="userDao" parent="baseDao" class="com.test.app.project.dao.UserDAOImpl">
</bean>

<bean id="userService" class="com.test.app.project.services.UserServiceImpl">
    <property name="userDao" ref="userDao" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

DAO类getAll方法

代码语言:javascript
运行
复制
public <T> List<T> getAll(final Class<T> type) {
        long startTime = System.nanoTime();
        List<T> afterGetAll = getSessionFactory().getCurrentSession().createSQLQuery("SELECT user_id,username,email,is_active FROM app_users")
                .addScalar("user_id", LongType.INSTANCE)
                .addScalar("username", StringType.INSTANCE)
                .addScalar("email", StringType.INSTANCE)
                .addScalar("is_active", IntegerType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(UserModel.class)).list();
        //List<T> afterGetAll = getSessionFactory().getCurrentSession().createCriteria(type).list();
        long endTime = System.nanoTime();
        long duration = (endTime - startTime); 
        logger.info("============getAll=============== Execution Timestamp: " + duration/1000000 + "milliseconds");
        return afterGetAll;
    }

服务类调用上面的dao

代码语言:javascript
运行
复制
@Transactional(propagation=Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED)
@Service
public class UserServiceImpl implements UserService{
...
    @Override
    public <T> List<T> getAll(Class<T> type) {
        List<T> userList = userDao.getAll(type);
        return userList;
    }
...
}

配置/代码中的任何建议都可以提高性能,这也受到欢迎。先谢谢

Update#1:启用hibernate统计之后的,我可以推断,由于以下统计信息,大部分时间没有花在执行语句上。

代码语言:javascript
运行
复制
2015-10-14 10:45:46 INFO  StatisticalLoggingSessionEventListener:275 - Session M
etrics {
    298847 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    914957 nanoseconds spent preparing 1 JDBC statements;
    335661830 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and
0 collections);
    5735 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 en
tities and 0 collections)
}

2015-10-14 10:45:46 INFO  AdminOperationController:51 - =======/admin/operation/
UserManagement Execution Timestamp:====== 3051milliseconds

结果表明,只调用该服务的执行控制器类与hibernate执行语句的执行时间相差近10倍。

Update#2

我试图添加一些毫秒时间戳,以跟踪哪个进程花费了大部分时间。后来,我发现了大部分时间用于将hibernate事务公开为jdbc事务,并在每次服务操作之后执行事务。统计查找日志如下所示

代码语言:javascript
运行
复制
2015-10-15 18:00:13,768 DEBUG HibernateTransactionManager:448 - Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2b237512 updates=org.hibernate.engine.spi.ExecutableList@24db06de deletions=org.hibernate.engine.spi.ExecutableList@279febb9 orphanRemovals=org.hibernate.engine.spi.ExecutableList@742cd301 collectionCreations=org.hibernate.engine.spi.ExecutableList@2ad1223d collectionRemovals=org.hibernate.engine.spi.ExecutableList@81ee8c1 collectionUpdates=org.hibernate.engine.spi.ExecutableList@2542db11 collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@483c4c33 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
2015-10-15 18:00:13,847 DEBUG HibernateTransactionManager:516 - Exposing Hibernate transaction as JDBC transaction [ConnectionHandle{url=jdbc:mysql://test, user=test, debugHandle=null, lastResetAgoInSec=18, lastUsedAgoInSec=18, creationTimeAgoInSec=18}]
2015-10-15 18:00:13,924 DEBUG SQL:109 - 
    /* dynamic native SQL query */ SELECT
        user_id,
        username,
        email,
        is_active 
    FROM
        app_users
2015-10-15 18:00:14,018 TRACE BasicExtractor:78 - extracted value ([user_id] : [BIGINT]) - [43]
...
...
2015-10-15 18:00:14,177 TRACE BasicExtractor:78 - extracted value ([username] : [VARCHAR]) - [username33]
2015-10-15 18:00:14,178 TRACE BasicExtractor:78 - extracted value ([email] : [VARCHAR]) - [ss@ss.com]
2015-10-15 18:00:14,178 TRACE BasicExtractor:78 - extracted value ([is_active] : [INTEGER]) - [0]
2015-10-15 18:00:14,178 TRACE BasicExtractor:78 - extracted value ([user_id] : [BIGINT]) - [136]
2015-10-15 18:00:14,179 TRACE BasicExtractor:78 - extracted value ([username] : [VARCHAR]) - [username34]
2015-10-15 18:00:14,179 TRACE BasicExtractor:78 - extracted value ([email] : [VARCHAR]) - [ss2@ss.com]
2015-10-15 18:00:14,180 TRACE BasicExtractor:78 - extracted value ([is_active] : [INTEGER]) - [0]
2015-10-15 18:00:14,283 INFO  BaseDAOImpl:117 - ============getAll=============== Execution Timestamp: 433milliseconds
2015-10-15 18:00:14,284 DEBUG HibernateTransactionManager:759 - Initiating transaction commit
2015-10-15 18:00:14,286 DEBUG HibernateTransactionManager:580 - Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2b237512 updates=org.hibernate.engine.spi.ExecutableList@24db06de deletions=org.hibernate.engine.spi.ExecutableList@279febb9 orphanRemovals=org.hibernate.engine.spi.ExecutableList@742cd301 collectionCreations=org.hibernate.engine.spi.ExecutableList@2ad1223d collectionRemovals=org.hibernate.engine.spi.ExecutableList@81ee8c1 collectionUpdates=org.hibernate.engine.spi.ExecutableList@2542db11 collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@483c4c33 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
2015-10-15 18:00:14,496 DEBUG HibernateTransactionManager:669 - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@2b237512 updates=org.hibernate.engine.spi.ExecutableList@24db06de deletions=org.hibernate.engine.spi.ExecutableList@279febb9 orphanRemovals=org.hibernate.engine.spi.ExecutableList@742cd301 collectionCreations=org.hibernate.engine.spi.ExecutableList@2ad1223d collectionRemovals=org.hibernate.engine.spi.ExecutableList@81ee8c1 collectionUpdates=org.hibernate.engine.spi.ExecutableList@2542db11 collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@483c4c33 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] after transaction
2015-10-15 18:00:14,499 INFO  StatisticalLoggingSessionEventListener:275 - Session Metrics {
    21735 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    10155810 nanoseconds spent preparing 1 JDBC statements;
    69653167 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    11795265 nanoseconds spent performing 1 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    69732 nanoseconds spent performing 1 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    31394 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
2015-10-15 18:00:14,639 INFO  AdminOperationController:49 - =======/admin/operation/UserManagement Execution Timestamp:====== 924milliseconds

通过初始化缓存

代码语言:javascript
运行
复制
2015-10-15 18:00:22,410 DEBUG HibernateTransactionManager:516 - Exposing Hibernate transaction as JDBC transaction [ConnectionHandle{url=jdbc:mysql://test, user=test, debugHandle=null, lastResetAgoInSec=22, lastUsedAgoInSec=22, creationTimeAgoInSec=22}]
2015-10-15 18:00:22,417 INFO  BaseDAOImpl:117 - ============getAll=============== Execution Timestamp: 4milliseconds
2015-10-15 18:00:22,418 DEBUG HibernateTransactionManager:759 - Initiating transaction commit
2015-10-15 18:00:22,419 DEBUG HibernateTransactionManager:580 - Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@19acc826 updates=org.hibernate.engine.spi.ExecutableList@1e8843f5 deletions=org.hibernate.engine.spi.ExecutableList@425997c orphanRemovals=org.hibernate.engine.spi.ExecutableList@407f9e04 collectionCreations=org.hibernate.engine.spi.ExecutableList@7a5f39b0 collectionRemovals=org.hibernate.engine.spi.ExecutableList@1c49094 collectionUpdates=org.hibernate.engine.spi.ExecutableList@fefe574 collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4ec12ad8 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
2015-10-15 18:00:22,625 DEBUG HibernateTransactionManager:669 - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@19acc826 updates=org.hibernate.engine.spi.ExecutableList@1e8843f5 deletions=org.hibernate.engine.spi.ExecutableList@425997c orphanRemovals=org.hibernate.engine.spi.ExecutableList@407f9e04 collectionCreations=org.hibernate.engine.spi.ExecutableList@7a5f39b0 collectionRemovals=org.hibernate.engine.spi.ExecutableList@1c49094 collectionUpdates=org.hibernate.engine.spi.ExecutableList@fefe574 collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@4ec12ad8 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] after transaction
2015-10-15 18:00:22,627 INFO  StatisticalLoggingSessionEventListener:275 - Session Metrics {
    19621 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    0 nanoseconds spent preparing 0 JDBC statements;
    0 nanoseconds spent executing 0 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    2170444 nanoseconds spent performing 1 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    19018 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)
}
2015-10-15 18:00:22,766 INFO  AdminOperationController:49 - =======/admin/operation/UserManagement Execution Timestamp:====== 425milliseconds

有人能建议我如何改善这种情况吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-15 15:26:53

终于解决了这个问题。除了配置解决方案(请参阅我编辑的文章,我使用缓存初始化),我重构我的代码,以便在一个事务服务方法中尽可能地进行适当的DAO操作(在此之前,我的事务服务只有非常简化的方法,也就是说,我可能需要为一个工作流调用几个事务服务方法(例如,注册一个新用户)。这样做是非常昂贵的。

这进一步提高了我的表现。

正如我们在我的文章Update#2中看到的那样,瓶颈在于事务提交。这可能是数据库服务器问题。现在,我将数据库更改为localhost。速度由400~500 has进一步提高到20 has。

票数 0
EN

Stack Overflow用户

发布于 2015-10-13 18:29:41

请找出一些建议:

  1. hibernate.show_sql设置为"false",并确保Hibernate日志记录在尽可能低的日志级别上运行。
  2. 延迟加载定义为首选关联加载策略。
  3. 在查询和条件上设置@Transactional(readOnly = true),当返回的对象永远不会被修改时。
  4. 大多数查询都不能从缓存中获益,因此默认情况下,查询不会被缓存。若要启用缓存,请调用Query.setCacheable(true).
  5. 您可以激活Hibernate Statistics来分析性能问题(属性hibernate.generate_statistics设置为true)。
  6. 验证表上有索引
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33108413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档