Оптимизация производительности запросов / огм SDN4 Neo4j 3.0.3
В моем проекте Neo4j 3.0.3 Spring Data Neo4j 4.2.0.SNAPSHOT у меня есть следующие объекты:
@NodeEntity
public abstract class BaseEntity {
@GraphId
private Long id;
private Date createDate;
private Date updateDate;
...
}
@NodeEntity
public class Decision extends BaseEntity {
private final static String CONTAINS = "CONTAINS";
private final static String DEFINED_BY = "DEFINED_BY";
private String name;
@Relationship(type = CONTAINS, direction = Relationship.INCOMING)
private Set<Decision> parentDecisions = new HashSet<>();
@Relationship(type = CONTAINS, direction = Relationship.OUTGOING)
private Set<Decision> childDecisions = new HashSet<>();
@Relationship(type = DEFINED_BY, direction = Relationship.INCOMING)
private Set<CriterionGroup> criterionGroups = new HashSet<>();
@Relationship(type = DEFINED_BY, direction = Relationship.INCOMING)
private Set<Criterion> criteria = new HashSet<>();
...
}
@NodeEntity
public class Criterion extends BaseEntity {
private final static String CONTAINS = "CONTAINS";
private final static String DEFINED_BY = "DEFINED_BY";
private String name;
@Relationship(type = CONTAINS, direction = Relationship.INCOMING)
private CriterionGroup group;
@Relationship(type = DEFINED_BY, direction = Relationship.OUTGOING)
private Decision owner;
...
}
@NodeEntity
public class Vote extends Authorable {
private final static String CONTAINS = "CONTAINS";
@Relationship(type = CONTAINS, direction = Relationship.INCOMING)
private VoteGroup group;
private double weight;
private String description;
...
}
@NodeEntity
public class VoteGroup extends BaseEntity {
private static final String VOTED_ON = "VOTED_ON";
private final static String VOTED_FOR = "VOTED_FOR";
private final static String CONTAINS = "CONTAINS";
@Relationship(type = VOTED_FOR, direction = Relationship.OUTGOING)
private Decision decision;
@Relationship(type = VOTED_ON, direction = Relationship.OUTGOING)
private Criterion criterion;
@Relationship(type = CONTAINS, direction = Relationship.OUTGOING)
private Set<Vote> votes = new HashSet<>();
private double avgVotesWeight;
private long totalVotesCount;
...
}
У меня есть метод тестирования, который создает тестовые узлы в базе данных Embeded Ne04j. Прямо сейчас, после переноса моего кода с Neo4j 2x на 3x и SDN3x на SDN4x, я вижу заметное снижение производительности при создании этих узлов.
Я более чем уверен, что это связано с некоторыми проблемами в моей реализации, а не с самой технологией, поэтому я хотел бы попросить помочь мне найти причины низкой производительности.
Например, у меня есть следующий метод:
@Override
public Vote createVote(Decision decision, Criterion criterion, User author, String description, double weight) {
VoteGroup voteGroup = getVoteGroupForDecisionOnCriterion(decision.getId(), criterion.getId());
if (voteGroup == null) {
voteGroup = new VoteGroup(decision, criterion, weight, 1);
} else {
long newTotalVotesCount = voteGroup.getTotalVotesCount() + 1;
double newAvgVotesWeight = (voteGroup.getAvgVotesWeight() * voteGroup.getTotalVotesCount() + weight) / newTotalVotesCount;
voteGroup.setAvgVotesWeight(newAvgVotesWeight);
voteGroup.setTotalVotesCount(newTotalVotesCount);
}
return voteRepository.save(new Vote(voteGroup, author, weight, description));
}
конструкторы:
public VoteGroup(Decision decision, Criterion criterion, double avgVotesWeight, long totalVotesCount) {
this.decision = decision;
this.criterion = criterion;
this.avgVotesWeight = avgVotesWeight;
this.totalVotesCount = totalVotesCount;
}
public Vote(VoteGroup group, User author, double weight, String description) {
this.group = group;
group.addVote(this);
setAuthor(author);
this.weight = weight;
this.description = description;
}
и метод хранилища:
@Query("MATCH (d:Decision)<-[:VOTED_FOR]-(vg:VoteGroup)-[:VOTED_ON]->(c:Criterion) WHERE id(d) = {decisionId} AND id(c) = {criterionId} RETURN vg")
VoteGroup getVoteGroupForDecisionOnCriterion(@Param("decisionId") Long decisionId, @Param("criterionId") Long criterionId);
Прямо сейчас производительность createVote
Метод существенно ухудшается с ростом количества узлов.
Один и тот же код на Neo4j 2x и SDN3 работал намного быстрее. Что может быть не так и как исправить проблему с производительностью?
ОБНОВЛЕНО
Это информация профайлера:
Похоже на методы:
CypherContext.deregisterOutgoingRelationships()
CypherContext.deregisterIncomingRelationships()
Сейчас у меня всего 22397 узлов в базе данных:
845 Decisions
2274 Criterion
9387 Vote
9387 VoteGroup
voteDao.createVote
метод выполняется 4194 - 8194 мс.
Например, на очень маленькой базе данных она начинает работать в следующий раз:
getVoteGroupForDecisionOnCriterion - 0-1ms
voteRepository.save - 9ms
и с ростом базы данных getVoteGroupForDecisionOnCriterion
работает со стабильным 0-1мс, но производительность voteRepository.save
очень быстро значительно ухудшается.
Итак, похоже, что узкое место voteRepository.save
метод.
Это мой Neo4jConfig:
@Configuration
@EnableNeo4jRepositories(basePackages = "com.example")
@EnableTransactionManagement
public class Neo4jConfig extends Neo4jConfiguration {
@Override
public SessionFactory getSessionFactory() {
return new SessionFactory("com.example");
}
}
ogm.properties:
driver=org.neo4j.ogm.drivers.bolt.driver.BoltDriver
URI=bolt://neo4j:password@localhost
Что может быть не так и как это исправить?