【发布时间】:2020-09-22 08:08:48
【问题描述】:
我正在使用 java spring boot 开发一个 Web 应用程序,并且我使用 H2 作为数据库。
我在插入数据时遇到了一些性能问题。我正确地进行了批量插入,但我注意到一段时间后插入速度变慢了很多。例如,插入前 N 个元素需要 100 秒,但随后需要 200 秒插入以下 N 个元素,然后 400 秒用于下一个 N 个元素,依此类推。
我正在努力寻找问题并解决它。有人可以帮忙吗?
为了进行批处理,我设置了应用程序属性:
spring.jpa.properties.hibernate.jdbc.batch_size=20
我正在插入这个实体:
@Getter
@Setter
@Entity
@Table(name = "entity_son")
public class EntitySon extends EntityFather{
protected EntitySon (){}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name ="anotherEntityId")
private AnotherEntity AnotherEntityId;
}
继承自该实体:
@Getter
@Setter
@MappedSuperclass
public abstract class EntityFather{
@Id
@SequenceGenerator(name = "SEQ", initialValue = 1, allocationSize = 20, sequenceName = "EntitySequence")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ")
@Column(name ="entityId")
private Long entityFatherId;
}
我正在使用 liquibase 以这种方式生成序列:
databaseChangeLog:
- changeSet:
id: createSequence
author: liquibase-docs
changes:
- createSequence:
sequenceName: EntitySequence
incrementBy: 20
最后我以这种方式进行批量插入:
private void saveEntitySon(List<EntitySon> entitySons){
long BATCH_SIZE = 20L;
long batchIter = 0;
while(true) {
List<EntitySon> batch = entitySons.stream().skip(batchIter*BATCH_SIZE)
.limit(BATCH_SIZE*(batchIter+1)).collect(Collectors.toList());
if (batch.size() < BATCH_SIZE) {
logger.info("Saving line difference by line difference");
for (EntitySon entitySon : batch) {
entitySonRepository.save(entitySon)
}
return;
}else{
entitySonRepository.saveAll(batch)
}
batchIter++;
}
}
我还必须提到,如果我删除并重新创建数据库,我会在性能中看到相同的模式。
【问题讨论】:
-
也许你可以给我们看一些代码,否则将无法帮助你。从哪里开始?
-
好的,我会提供一些代码。我仍然很想知道你对这个问题的看法。
-
好吧,你的代码每次都在处理更多的实体——如果你删除数据库插入,它仍然表现出相同的行为吗?如果少于批次,也不确定为什么要插入单个项目。最后,它应该自动批处理——我不知道你为什么每次都手动创建一个列表;只需每
batch个项目刷新一次会话。 -
另外,儿子扩展父亲只是……很奇怪。
-
对不起,代码有点匿名,所以有些事情没有真正意义,但这里的关键是性能。我目前专注于插入性能,到目前为止读取不是问题
标签: spring-boot hibernate spring-data-jpa h2