Java hibernate的性能很差
我读了很多关于设置hibernate以保存大量新实体的内容,但是我错过了一些东西,因为插入性能非常差 这是我的配置 休眠配置:Java hibernate的性能很差,java,performance,hibernate,Java,Performance,Hibernate,我读了很多关于设置hibernate以保存大量新实体的内容,但是我错过了一些东西,因为插入性能非常差 这是我的配置 休眠配置: @Configuration @EnableTransactionManagement @ComponentScans(value = { @ComponentScan("com.xxxxx)}) public class HibernateConfiguration { @Bean public LocalSessionFactoryBean sessionFac
@Configuration
@EnableTransactionManagement
@ComponentScans(value = { @ComponentScan("com.xxxxx)})
public class HibernateConfiguration
{
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.xxxx" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(XXXX);
dataSource.setUsername(XXXX);
dataSource.setPassword(XXXX);
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery("SELECT 1");
dataSource.setInitialSize(3);
dataSource.setMaxActive(10);
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put(Environment.DIALECT, "org.hibernate.dialect.PostgreSQL95Dialect");
properties.put(Environment.SHOW_SQL, false);
properties.put(Environment.FORMAT_SQL, false);
properties.put("hibernate.default-lazy", true);
properties.put(Environment.USE_NEW_ID_GENERATOR_MAPPINGS, true);
properties.put(Environment.HBM2DDL_AUTO, "none");
properties.put(Environment.STATEMENT_BATCH_SIZE, 50);
properties.put(Environment.STATEMENT_FETCH_SIZE, 400);
properties.put(Environment.ORDER_INSERTS, true);
properties.put(Environment.ORDER_UPDATES, true);
properties.put(Environment.BATCH_VERSIONED_DATA, true);
properties.put(Environment.GENERATE_STATISTICS, true);
properties.put(Environment.HQL_BULK_ID_STRATEGY, InlineIdsSubSelectValueListBulkIdStrategy.class);
return properties;
}
@Bean
public HibernateTransactionManager transactionManager()
{
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation()
{
return new PersistenceExceptionTranslationPostProcessor();
}
}
对于我的测试,我创建了一个没有任何关系的简单表
实体:
@Entity
@Table(name="performance_test")
@NamedQuery(name="PerformanceTest.findAll", query="SELECT t FROM PerformanceTest t")
public class PerformanceTest
{
@Id
@Id
@GenericGenerator(
name = "PERFORMANCE_TEST_ID_GENERATOR",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
@Parameter(name = "sequence_name", value = "performance_test_id_seq"),
@Parameter(name = "optimizer", value = "pooled-lo"),
@Parameter(name = "increment_size", value = "1")
}
)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PERFORMANCE_TEST_ID_GENERATOR")
private Long id;
private Long id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(name="salary")
private Integer salary;
public PerformanceTest(){};
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
public Integer getSalary()
{
return salary;
}
public void setSalary(Integer salary)
{
this.salary = salary;
}
}
DAO实现(我使用了这两种方法,但没有显著改进)
@Override
public void saveBulkElement (Set<T> listOfElement,Integer bulkSize)
{
if(listOfElement == null || listOfElement.size() == 0)
return;
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.setJdbcBatchSize(batchSize);
try
{
int flushIndex = 0;
Iterator<T> ite = listOfElement.iterator();
while (ite.hasNext())
{
T element = (T) ite.next();
session.persist(element);
flushIndex++;
int size = bulkSize != null ? bulkSize:batchSize;
if((flushIndex % size == 0 && flushIndex > 0) || !ite.hasNext())
{
session.flush();
session.clear();
}
}
tx.commit();
}
catch (HibernateException e)
{
if (tx != null)
tx.rollback();
}
finally
{
session.close();
}
}
@Override
public void saveStatelessBulkElement (Set<T> listOfElement)
{
if(listOfElement == null || listOfElement.size() == 0)
return;
StatelessSession session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();
session.setJdbcBatchSize(listOfElement.size() < statelessBatchSize ? listOfElement.size():statelessBatchSize);
try
{
Iterator<T> ite = listOfElement.iterator();
while (ite.hasNext())
{
T element = (T) ite.next();
session.insert(element);
}
tx.commit();
}
catch (HibernateException e)
{
if (tx != null)
tx.rollback();
}
finally
{
session.close();
}
}
只有100件物品花费了14秒
我是否遗漏了hibernate的配置
我用一个好的生成器更新了我的实体,问题仍然存在
===================================================
第一次更新:
我检查DB seq生成器
Sequence "recntrek.performance_test_id_seq"
Column | Type | Value
---------------+---------+-------------------------
sequence_name | name | performance_test_id_seq
last_value | bigint | 293551
start_value | bigint | 1
increment_by | bigint | 1
max_value | bigint | 9223372036854775807
min_value | bigint | 1
cache_value | bigint | 1
log_cnt | bigint | 32
is_cycled | boolean | f
is_called | boolean | t
我将增量和缓存值更改为50
我重新运行测试,耗时1.4秒
我用10000个新元素做了另一个测试,耗时约30秒
这是一个很大的改进,但从Vlad Mihalcea的这一点来看,我离获得良好的性能还有很长的路要走看来,糟糕的性能与数据库序列的定义有关 以下是不同序列配置的一些结果:
@Configuration
@EnableTransactionManagement
@ComponentScans(value = { @ComponentScan("com.xxxxx)})
public class HibernateConfiguration
{
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.xxxx" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(XXXX);
dataSource.setUsername(XXXX);
dataSource.setPassword(XXXX);
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery("SELECT 1");
dataSource.setInitialSize(3);
dataSource.setMaxActive(10);
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put(Environment.DIALECT, "org.hibernate.dialect.PostgreSQL95Dialect");
properties.put(Environment.SHOW_SQL, false);
properties.put(Environment.FORMAT_SQL, false);
properties.put("hibernate.default-lazy", true);
properties.put(Environment.USE_NEW_ID_GENERATOR_MAPPINGS, true);
properties.put(Environment.HBM2DDL_AUTO, "none");
properties.put(Environment.STATEMENT_BATCH_SIZE, 50);
properties.put(Environment.STATEMENT_FETCH_SIZE, 400);
properties.put(Environment.ORDER_INSERTS, true);
properties.put(Environment.ORDER_UPDATES, true);
properties.put(Environment.BATCH_VERSIONED_DATA, true);
properties.put(Environment.GENERATE_STATISTICS, true);
properties.put(Environment.HQL_BULK_ID_STRATEGY, InlineIdsSubSelectValueListBulkIdStrategy.class);
return properties;
}
@Bean
public HibernateTransactionManager transactionManager()
{
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation()
{
return new PersistenceExceptionTranslationPostProcessor();
}
- 100行:increment_by和cache_值被设置为1,这需要14秒
- 100行:增量_by和缓存_值被设置为50,大约需要1.4秒
- 10K行:增量_by和缓存_值设置为50,这需要约30秒
- 10K行:增量_by和缓存_值设置为500,需要约5秒
- 10K行:增量_by和缓存_值被设置为1000,需要约4秒
希望这将有助于…可能的重复我有其他具有良好生成器定义的表,我也有相同的问题..如果id具有从相同的
性能测试\u id_seq
中获取的默认值,如序列或bigserial
类型所定义,则可以使用@GeneratedValue(strategy=GenerationType.IDENTITY)
并保存一半的查询,但我认为改进不会很大。值得一试。
@GenericGenerator(
name = "PERFORMANCE_TEST_ID_GENERATOR",
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
@Parameter(name = "sequence_name", value = "performance_test_id_seq"),
@Parameter(name = "optimizer", value = "pooled-lo"),
@Parameter(name = "increment_size", value = "1")
}
)