在我们的系统中,存在一种(非常常见的)情况,其中用户的操作可以触发涉及在节点和之间设置/移除标签的操作,其总数量为数十万个实体。 (从100K节点中删除标签A
,将标签B
设置为80K标签,将属性[x,y,z]
设置为20K节点,依此类推)。当然,我无法在一个事务中将它们全部压缩,并且由于这些节点可以很容易地分成大量的子集,我在一些单独的事务中执行操作,当然,这些事务中断了所有的ACIDity,但在性能方面满足我们。但是,如果我尝试将这些事务嵌套到一个大的来统治它们,那么顶级事务会尝试跟踪所有内部事务对DB的更新,这当然会导致表现极差。
你们有什么建议我解决这个问题的?
我的配置(以及相关部分):
"org.neo4j.server.database.mode" : "HA",
"use_memory_mapped_buffers" : "true",
"neostore.nodestore.db.mapped_memory" : "450M",
"neostore.relationshipstore.db.mapped_memory" : "450M",
"neostore.propertystore.db.mapped_memory" : "450M",
"neostore.propertystore.db.strings.mapped_memory" : "300M",
"neostore.propertystore.db.arrays.mapped_memory" : "50M",
"cache_type" : "hpc",
"dense_node_threshold" : "15",
"query_cache_size" : "150"
非常感谢任何提示和线索:)
答案 0 :(得分:3)
您是正确的,因为在同一事务中执行用户操作而修改数十万个实体并不符合要求。正确指出,Neo4j中的嵌套交易只是“安慰剂”交易。
我首先考虑实现目标的替代策略(我对此一无所知),而无需更新这么多实体。
如果无法替代,我会问用户操作后短时间内是否可以进行更新。如果答案是肯定的,那么我会在持久队列中存储关于用户操作的消息,我将异步处理。这样,用户调用快速返回,最终更新。
最后,如果用户操作和大型更新之间的时间可以接受更长时间,我会考虑和“代理”不断抓取图形并更新它遇到的实体的标签,而不是交易驱动的更新。看看GraphAware NodeRank的灵感。