【问题标题】:Building relationships in Neo4j via Py2neo is very slow通过 Py2neo 在 Neo4j 中建立关系非常慢
【发布时间】:2018-03-02 02:08:11
【问题描述】:

我们在数据库中有 5 种不同类型的节点。最大的有~290k,最小的只有~3k。每个节点类型都有一个 id 字段,它们都被索引。我正在使用py2neo 建立关系,但速度很慢(每秒插入 2 个关系)

我使用pandas 从关系 csv 中读取,迭代每一行以创建包含在事务中的关系。我尝试在一个事务中批量处理 10k 个创建语句,但它似乎并没有提高很多速度。

下面是代码:

df = pd.read_csv(r"C:\relationship.csv",dtype = datatype, skipinitialspace=True, usecols=fields)
df.fillna('',inplace=True)

def f(node_1 ,rel_type, node_2):
    try:
        tx = graph.begin()
        tx.evaluate('MATCH (a {node_id:$label1}),(b {node_id:$label2}) MERGE (a)-[r:'+rel_type+']->(b)',
                    parameters = {'label1': node_1, 'label2': node_2})
        tx.commit()
    except Exception as e:
        print(str(e))

for index, row in df.iterrows():
    if(index%1000000 == 0):
        print(index)
    try:
        f(row["node_1"],row["rel_type"],row["node_2"])
    except:
        print("error index: " + index)

有人可以帮助我在这里做错了什么。谢谢!

【问题讨论】:

    标签: pandas neo4j py2neo


    【解决方案1】:

    您声明有“5 种不同类型的节点”(我将其解释为 5 个节点 标签,在 neo4j 术语中)。此外,您还声明他们的 id 属性已被编入索引。

    但是您的 f() 函数根本没有生成使用标签的 Cypher 查询,也没有使用 id 属性。为了利用您的索引,您的 Cypher 查询必须指定节点标签和 id 值。

    由于目前在执行MATCH 时没有有效的方法来参数化标签,因此以下版本的f() 函数会生成具有硬编码标签(以及硬编码关系类型)的 Cypher 查询:

    def f(label_1, id_1, rel_type, label_2, id_2):
        try:
            tx = graph.begin()
            tx.evaluate(
                    'MATCH' +
                    '(a:' + label_1 + '{id:$id1}),' +
                    '(b:' + label_2 + '{id:$id2}) ' +
                    'MERGE (a)-[r:'+rel_type+']->(b)',
                parameters = {'id1': id_1, 'id2': id_2})
            tx.commit()
        except Exception as e:
            print(str(e))
    

    调用f() 的代码也必须更改为同时传递标签名称和abid 值。希望您的 df 行将包含该数据(或足以让您获得该数据的信息)。

    【讨论】:

    • 每个节点标签都有索引的node_id属性,所以如果我没有在匹配中指定标签,它根本无法使用索引?关系 csv 仅包含起始节点 id、关系、结束节点 id。我可以通过检查关系找出开始节点标签和结束节点标签,但是关系太多了,这样做代码会变得很难看。
    • 如果您的查询指定了节点标签和索引属性值,索引只能用于匹配节点。因此,您似乎必须添加代码来检查关系(如果您无法更改 CSV 文件内容)。
    【解决方案2】:

    如果您的目标是获得更好的性能,那么您需要考虑使用不同的模式来加载这些,即批处理。您当前正在为每个关系运行一个 Cypher MERGE 语句,并将其包装在单独的函数调用中的自己的事务中。

    通过查看每个事务或每个函数调用的多个语句来批处理这些将减少网络跃点的数量并应该提高性能。

    【讨论】:

    • 我在一个事务中尝试了批处理 10k 合并语句,但它似乎并没有显着提高性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多