Оптимизация производительности запросов / огм 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

Что может быть не так и как это исправить?

0 ответов

Другие вопросы по тегам