【发布时间】:2015-10-01 10:14:17
【问题描述】:
我编写了一些简单的 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();
}
'Element' 类确实需要知道它的值,但 'Attribute' 类根本不关心值。
一个属性在 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)。
这就是为什么我认为这里存在性能问题。还是我做错了什么?
感谢您的帮助
【问题讨论】:
标签: neo4j spring-data-neo4j-4 neo4j-ogm