我编写了一些简单的 java 代码,但在 SDN4 中遇到了一些我在 SDN3 中没有的糟糕性能。我怀疑 find repositories methods depth 参数不能完全按照它应该的方式工作。让我解释一下问题:
这是我的 java 类(这只是一个示例),其中我删除了 getter、setter、contructors,......
第一类是“元素”:
@NodeEntity
public class Element {
@GraphId
private Long id;
private int age;
private String uuid;
@Relationship(type = "HAS_VALUE", direction = Relationship.OUTGOING)
private Set<Value> values = new HashSet<Value>();
第二个是“属性”
@NodeEntity
public class Attribute {
@GraphId
private Long id;
@Relationship(type = "HAS_PROPERTIES", direction = Relationship.OUTGOING)
private Set<HasInterProperties> properties;
“值”类允许我的用户在元素上为特定属性添加值:
@RelationshipEntity(type = "HAS_VALUE")
public class Value {
@GraphId
private Long id;
@StartNode
Element element;
@EndNode
Attribute attribute;
private Integer value;
private String uuid;
public Value() {
}
public Value(Element element, Attribute attribute, Integer value) {
this.element = element;
this.attribute = attribute;
this.value = value;
this.element.getValues().add(this);
this.uuid = UUID.randomUUID().toString();
}
“元素”类确实需要知道它的值,但“属性”类根本不关心值。
一个属性在 InternationalizedProperties 类上有引用,如下所示:
@NodeEntity
public class InternationalizedProperties {
@GraphId
private Long id;
private String name;
属性与其 InternationalizedProperties 之间的关系实体如下所示:
@RelationshipEntity(type = "HAS_PROPERTIES")
public class HasInterProperties {
@GraphId
private Long id;
@StartNode
private Attribute attribute;
@EndNode
private InternationalizedProperties properties;
private String locale;
然后我创建了一个小的 main 方法来创建两个属性和 10000 个元素。我的所有元素都具有第一个属性的特定值,但没有第二个属性的值(它们之间没有关系)。这两个属性都有两个不同的国际化属性。这是一个示例:
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/*.xml");
Session session = context.getBean(Session.class);
session.query("START n=node(*) OPTIONAL MATCH n-[r]-() WHERE ID(n) <> 0 DELETE n,r", new HashMap<String, Object>());
ElementRepository elementRepository = context.getBean(ElementRepository.class);
AttributeRepository attributeRepository = context.getBean(AttributeRepository.class);
InternationalizedPropertiesRepository internationalizedPropertiesRepository = context.getBean(InternationalizedPropertiesRepository.class);
HasInterPropertiesRepository hasInterPropertiesRepository = context.getBean(HasInterPropertiesRepository.class);
//Creation of an attribute object with two internationalized properties
Attribute att = new Attribute();
attributeRepository.save(att);
InternationalizedProperties p1 = new InternationalizedProperties();
p1.setName("bonjour");
internationalizedPropertiesRepository.save(p1);
InternationalizedProperties p2 = new InternationalizedProperties();
p2.setName("hello");
internationalizedPropertiesRepository.save(p2);
hasInterPropertiesRepository.save(new HasInterProperties(att, p1, "fr"));
hasInterPropertiesRepository.save(new HasInterProperties(att, p2, "en"));
LOGGER.info("First attribut id is {}", att.getId());
//Creation of 1000 elements having a differnt value on a same attribute
for(int i = 0; i< 10000; i++) {
Element elt = new Element();
new Value(elt, att, i);
elementRepository.save(elt);
if(i%50 == 0) {
LOGGER.info("{} elements created. Last element created with id {}", i+1, elt.getId());
}
}
//Another attribut without any values from element.
Attribute att2 = new Attribute();
attributeRepository.save(att2);
InternationalizedProperties p12 = new InternationalizedProperties();
p12.setName("bonjour");
internationalizedPropertiesRepository.save(p12);
InternationalizedProperties p22 = new InternationalizedProperties();
p22.setName("hello");
internationalizedPropertiesRepository.save(p22);
hasInterPropertiesRepository.save(new HasInterProperties(att2, p12, "fr"));
hasInterPropertiesRepository.save(new HasInterProperties(att2, p22, "en"));
LOGGER.info("Second attribut id is {}", att2.getId());
最后,在另一个主要方法中,我尝试多次获取第一个属性和第二个属性:
private static void getFirstAttribute(AttributeRepository attributeRepository) {
StopWatch st = new StopWatch();
st.start();
Attribute attribute = attributeRepository.findOne(25283L, 1);
LOGGER.info("time to get attribute (some element have values on it) is {}ms", st.getTime());
}
private static void getSecondAttribute(AttributeRepository attributeRepository) {
StopWatch st = new StopWatch();
st.start();
Attribute attribute2 = attributeRepository.findOne(26286L, 1);
LOGGER.info("time to get attribute (no element have values on it) is {}ms", st.getTime());
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring/*.xml");
AttributeRepository attributeRepository = context.getBean(AttributeRepository.class);
getFirstAttribute(attributeRepository);
getSecondAttribute(attributeRepository);
getFirstAttribute(attributeRepository);
getSecondAttribute(attributeRepository);
getFirstAttribute(attributeRepository);
getSecondAttribute(attributeRepository);
getFirstAttribute(attributeRepository);
getSecondAttribute(attributeRepository);
}
以下是此执行的日志:
time to get attribute (some element have values on it) is 2983ms
time to get attribute (no element have values on it) is 4ms
time to get attribute (some element have values on it) is 1196ms
time to get attribute (no element have values on it) is 2ms
time to get attribute (some element have values on it) is 1192ms
time to get attribute (no element have values on it) is 3ms
time to get attribute (some element have values on it) is 1194ms
time to get attribute (no element have values on it) is 3ms
获取第二个属性(以及由于 depth=1 而获得的国际化属性)非常快,但获取第一个属性仍然非常缓慢。我知道有很多关系(确切地说是 10000 个)指向第一个属性,但是当我想获得一个具有其国际化属性的属性时,我显然不想获得所有指向它的值。(因为未在 Attribute 类上指定 Set)。
这就是为什么我认为这里存在性能问题。还是我做错了什么?
谢谢你的帮助