Java 使用Hibernate二级缓存和HSQL的插入/更新速率令人失望

Java 使用Hibernate二级缓存和HSQL的插入/更新速率令人失望,java,spring,hibernate,hsqldb,ehcache,Java,Spring,Hibernate,Hsqldb,Ehcache,我需要能够以每秒5000次以上的速度写入数据库。目前,我无法管理该数字的10%以上 我使用Spring来配置我的数据源(HSQL)和Hibernate作为我的Jpa提供者 我的实体都是平面的(没有复杂的对象树),我使用了Hibernate二级缓存(EhCache),并发策略设置为ConcurrentyStrategy.READ-WRITE 以下是我的数据源bean的Spring上下文: <bean id="commandsTransactionManager" class="org.sp

我需要能够以每秒5000次以上的速度写入数据库。目前,我无法管理该数字的10%以上

我使用Spring来配置我的数据源(HSQL)和Hibernate作为我的Jpa提供者

我的实体都是平面的(没有复杂的对象树),我使用了Hibernate二级缓存(EhCache),并发策略设置为ConcurrentyStrategy.READ-WRITE

以下是我的数据源bean的Spring上下文:

 <bean id="commandsTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="commandEmf"/>

<tx:annotation-driven transaction-manager="commandsTransactionManager" />

<!-- Commmands Data Source Configuration -->
<bean id="commandsDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc-commands.driverClassName}"/>
    <property name="url" value="${jdbc-commands.url}"/>
    <property name="username" value="${jdbc-commands.username}"/>
    <property name="password" value="${jdbc-commands.password}"/>
    <property name="initialSize" value="10"/>
    <property name="maxActive" value="100"/>
    <property name="maxWait" value="-1"/>
</bean>

 <bean name="lazyConnectionDataSourceProxy" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
    <property name="targetDataSource" ref="commandsDataSource" />
</bean>

<!-- Commands Container Managed JPA Entity Manager Factory -->
<bean id="commandEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="commandsDataSource"/>
    <property name="persistenceUnitName" value="commands"/>
    <property name="jpaPropertyMap" ref="jpaPropertyMap"/>
    <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
                    p:showSql="false"  p:generateDdl="true" p:database="HSQL" p:databasePlatform="org.hibernate.dialect.HSQLDialect">
            </bean>
    </property>
</bean>

<util:map id="jpaPropertyMap" key-type="java.lang.String" value-type="java.lang.Object">
     <entry key="hibernate.hbm2ddl.auto" value="${jdbc-commands.ddlmode}" />
      <entry key="hibernate.cache.use_second_level_cache" value="true" />
      <entry key="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory"/>
</util:map>
为完整起见,以下是我的EhCache.xml文件中的缓存区域配置:

  <cache name="usersCache" maxElementsInMemory="10000"
  maxElementsOnDisk="10000" eternal="false" overflowToDisk="false"
  diskSpoolBufferSizeMB="20" timeToIdleSeconds="300"
  timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU"
  statistics = "true">
  </cache>

在Axon框架中,我发送命令来尝试和更改聚合的状态。这些命令在Spring的PlatformTransactionManager管理的事务范围内

命令调度是同步进行的,我每秒需要处理5000条命令。每个命令都将从缓存中获取聚合,更改其上的值,然后在调度下一个命令之前保留更改。问题在于获取/更新/插入行所需的时间,考虑到HYSQL和H2等公司所吹嘘的插入速率,我认为这会快得多

如果您有任何想法将我的速度提高一个数量级,我们将不胜感激


谢谢

我想您已经到了使用数据库、JDBC和单个insert语句所能做到的极限。Hibernate不是问题,缓存也不是。但您的数据库可能无法处理更多通过JDBC进行的插入


但如果你能设法使用,你可以更快。对于批量,我指的是样式
插入到您的_表中选择。。。从…
。从表中读取数据,修改一点,然后插入结果。有可能进行大容量插入。

如果此实体是典型的数据(即没有长字符串的几列),并且如果数据库操作是更新,则数据库性能应与此处描述的相当,每秒执行5000个事务(多个更新,每个事务一次选择和一次插入)使用基于磁盘的表

数据库在一个表中有4000000条记录。对于较大的表,性能会下降,尤其是当数据库大小超过使用JavaNIO内存映射文件的预设限制时


您还应该检查.script文件中的数据库架构,看看是否创建了不必要的索引,这会降低速度。

您是否尝试过不使用缓存?只是想看看它是否真的起了作用?我也遇到过类似的情况,缓存实际上一直在被刷新。我移除了它,性能得到了很大的提高。这不是一个答案,只是一个问题:)有趣-删除缓存绝对没有什么区别。我仍然可以在没有缓存的情况下每秒管理500次写入。这很有趣,不是吗?也许问题还应该是,为什么缓存没有起到作用。不幸的是,这超出了我的专业范围。真的吗?500次插入/秒大约是极限?HSQL网站拥有更多的功能(我知道它取决于对象大小/复杂度/变量类型),但我认为我至少可以从中获得另外一个数量级的功能——不是说55000 TPS吗?如果是这样,那么我实际运行的容量大约是可用容量的1%。非常不对劲。对于这样简单的对象,我可能能够拉出Hibernate,看看这是否有任何影响。感谢您的评论。它是55000 TPS,具有所有内存中的非持久表,但5000 TPS具有基于磁盘的缓存表。
  <cache name="usersCache" maxElementsInMemory="10000"
  maxElementsOnDisk="10000" eternal="false" overflowToDisk="false"
  diskSpoolBufferSizeMB="20" timeToIdleSeconds="300"
  timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU"
  statistics = "true">
  </cache>