在我的Neo4j/SDN 4應用程序中,我所有的Cypher查詢都基於內部Neo4j ID。Neo4j SDN 4 GraphId性能與指數
這是一個問題,因爲我無法在我的Web應用程序URL上依賴這些ID。 Neo4j可以重用這些ID,所以很有可能在未來的某個時間在相同的ID下我們可以找到絕對的另一個節點。
我試圖根據以下解決方案重新實現此邏輯:Using the graph to control unique id generation但注意到查詢性能下降。
從理論的角度來看,應在Cypher支架查詢基於與@Index(unique = true, primary = true
屬性)
例如:
@Index(unique = true, primary = true)
private Long uid;
entity.uid = {someId}
具有同樣性能的Cypher支架查詢其基於內部工作Neo4j的ID:
id(entity) = {someId}
修訂
這是:schema
輸出:
Indexes
ON :BaseEntity(uid) ONLINE
ON :Characteristic(lowerName) ONLINE
ON :CharacteristicGroup(lowerName) ONLINE
ON :Criterion(lowerName) ONLINE
ON :CriterionGroup(lowerName) ONLINE
ON :Decision(lowerName) ONLINE
ON :FlagType(name) ONLINE (for uniqueness constraint)
ON :HAS_VALUE_ON(value) ONLINE
ON :HistoryValue(originalValue) ONLINE
ON :Permission(code) ONLINE (for uniqueness constraint)
ON :Role(name) ONLINE (for uniqueness constraint)
ON :User(email) ONLINE (for uniqueness constraint)
ON :User(username) ONLINE (for uniqueness constraint)
ON :Value(value) ONLINE
Constraints
ON (flagtype:FlagType) ASSERT flagtype.name IS UNIQUE
ON (permission:Permission) ASSERT permission.code IS UNIQUE
ON (role:Role) ASSERT role.name IS UNIQUE
ON (user:User) ASSERT user.email IS UNIQUE
ON (user:User) ASSERT user.username IS UNIQUE
正如你可以看到我有:BaseEntity(uid)
BaseEntity
的指數是在我的實體層次結構中的基類,例如:
@NodeEntity
public abstract class BaseEntity {
@GraphId
private Long id;
@Index(unique = false)
private Long uid;
private Date createDate;
private Date updateDate;
...
}
@NodeEntity
public class Commentable extends BaseEntity {
...
}
@NodeEntity
public class Decision extends Commentable {
private String name;
}
威爾當我在查找(d:Decision) WHERE d.uid = {uid}
的示例時,將使用uid
索引?
PROFILE resuls - 內部ID VS索引屬性
查詢基於內部ID
PROFILE MATCH (parentD)-[:CONTAINS]->(childD:Decision)
WHERE id(parentD) = 1474333
MATCH (childD)-[relationshipValueRel1475199:HAS_VALUE_ON]-(filterCharacteristic1475199)
WHERE id(filterCharacteristic1475199) = 1475199
WITH relationshipValueRel1475199, childD
WHERE ([1, 19][0] <= relationshipValueRel1475199.value <= [1, 19][1])
WITH childD
MATCH (childD)-[relationshipValueRel1474358:HAS_VALUE_ON]-(filterCharacteristic1474358)
WHERE id(filterCharacteristic1474358) = 1474358
WITH relationshipValueRel1474358, childD
WHERE (ANY (id IN ['Compact'] WHERE id IN relationshipValueRel1474358.value))
WITH childD
MATCH (childD)-[relationshipValueRel1475193:HAS_VALUE_ON]-(filterCharacteristic1475193)
WHERE id(filterCharacteristic1475193) = 1475193
WITH relationshipValueRel1475193, childD
WHERE (ANY (id IN ['16:9', '3:2', '4:3', '1:1']
WHERE id IN relationshipValueRel1475193.value))
WITH childD
OPTIONAL MATCH (childD)-[vg:HAS_VOTE_ON]->(c)
WHERE id(c) IN [1474342, 1474343, 1474340, 1474339, 1474336, 1474352, 1474353, 1474350, 1474351, 1474348, 1474346, 1474344]
WITH childD, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes
WITH * MATCH (childD)-[ru:CREATED_BY]->(u:User)
WITH ru, u, childD , toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes
ORDER BY weight DESC
SKIP 0 LIMIT 10
RETURN ru, u, childD AS decision, weight, totalVotes,
[ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) | {entityId: id(entity), types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups,
[ (parentD)<-[:DEFINED_BY]-(c1)<-[vg1:HAS_VOTE_ON]-(childD) | {criterionId: id(c1), weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria,
[ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[v1:HAS_VALUE_ON]-(childD) WHERE NOT ((ch1)<-[:DEPENDS_ON]-()) | {characteristicId: id(ch1), value: v1.value, totalHistoryValues: toInt(v1.totalHistoryValues), description: v1.description, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics
PROFILE輸出:
Cypher支架版本:CYPHER 3.1,計劃者:成本,運行時:INTERPRETED 。 350554總分貝命中238毫秒。 CYPHER 3.1,規劃師:成本,運行時間:解釋爲基於索引的屬性UID
PROFILE MATCH (parentD)-[:CONTAINS]->(childD:Decision)
WHERE parentD.uid = 61
MATCH (childD)-[relationshipValueRel1475199:HAS_VALUE_ON]-(filterCharacteristic1475199)
WHERE filterCharacteristic1475199.uid = 15
WITH relationshipValueRel1475199, childD
WHERE ([1, 19][0] <= relationshipValueRel1475199.value <= [1, 19][1])
WITH childD
MATCH (childD)-[relationshipValueRel1474358:HAS_VALUE_ON]-(filterCharacteristic1474358)
WHERE filterCharacteristic1474358.uid = 10
WITH relationshipValueRel1474358, childD
WHERE (ANY (id IN ['Compact'] WHERE id IN relationshipValueRel1474358.value))
WITH childD
MATCH (childD)-[relationshipValueRel1475193:HAS_VALUE_ON]-(filterCharacteristic1475193)
WHERE filterCharacteristic1475193.uid = 14
WITH relationshipValueRel1475193, childD
WHERE (ANY (id IN ['16:9', '3:2', '4:3', '1:1']
WHERE id IN relationshipValueRel1475193.value))
WITH childD
OPTIONAL MATCH (childD)-[vg:HAS_VOTE_ON]->(c)
WHERE c.uid IN [26, 27, 24, 23, 20, 36, 37, 34, 35, 32, 30, 28]
WITH childD, vg.avgVotesWeight as weight, vg.totalVotes as totalVotes
WITH * MATCH (childD)-[ru:CREATED_BY]->(u:User)
WITH ru, u, childD , toFloat(sum(weight)) as weight, toInt(sum(totalVotes)) as totalVotes
ORDER BY weight DESC
SKIP 0 LIMIT 10
RETURN ru, u, childD AS decision, weight, totalVotes,
[ (parentD)<-[:DEFINED_BY]-(entity)<-[:COMMENTED_ON]-(comg:CommentGroup)-[:COMMENTED_FOR]->(childD) | {entityId: id(entity), types: labels(entity), totalComments: toInt(comg.totalComments)} ] AS commentGroups,
[ (parentD)<-[:DEFINED_BY]-(c1)<-[vg1:HAS_VOTE_ON]-(childD) | {criterionId: id(c1), weight: vg1.avgVotesWeight, totalVotes: toInt(vg1.totalVotes)} ] AS weightedCriteria,
[ (parentD)<-[:DEFINED_BY]-(ch1:Characteristic)<-[v1:HAS_VALUE_ON]-(childD) WHERE NOT ((ch1)<-[:DEPENDS_ON]-()) | {characteristicId: id(ch1), value: v1.value, totalHistoryValues: toInt(v1.totalHistoryValues), description: v1.description, valueType: ch1.valueType, visualMode: ch1.visualMode} ] AS valuedCharacteristics
暗號版本
查詢。 671326總分貝命中426毫秒。
是否有任何改善基於UID的表現機會呢?
感謝您的回答。現在,我試圖採用一種方法來重構我的系統,以避免ID重用的問題,並且我看到了以下模式 - 在我的網站上我將使用代理uid。如果id不需要放在web url中,我會使用內部的Neo4j id.So這個代理uuid將只用在web urls中,否則在客戶端的所有其他地方我都會使用內部的Neo4j ID。是否有意義 ? – alexanoid
有兩種方式通過ID訪問實體可能會使事情不必要地複雜化。我只會去用自定義的uuid。正如我所說索引是*快*,內部id和索引查找之間的差異將小於網絡延遲或一般OGM開銷的數量級。 –
我在單個查詢中使用了不同的ID(https://stackoverflow.com/questions/43824894/neo4j-cypher-query-structure-and-performance-optimization),所以使用基於一個純粹的UIDs被人眼所注意到。 – alexanoid