Neo4j C# 顶点创建性能

Neo4j C# vertex creation performance

我正在尝试使用 C# 在 Neo4j 上创建 1,000,000 个(微不足道的)顶点。 (社区版 2.3.2。)性能非常差 - 需要 900 多秒才能完成创建这些节点。我做某事效率低下吗?为什么需要这么长时间?

        var client = new GraphClient(new Uri("http://localhost:7474/db/data"), 
            "neo4j", "password");
        client.Connect();

        DateTime t = DateTime.Now;
        Debug.WriteLine(t);

        for (int j = 0; j < 100; j++ ) {
            using (var scope = new TransactionScope(
                TransactionScopeOption.Required,
                new TransactionOptions {IsolationLevel = IsolationLevel.ReadCommitted}
                ))
            {
                for (int i = 0; i < 10000; i++) {
                    var index = new Category { label = i.ToString() };
                            client.Cypher
                                .Create("(class:testItem {index})")
                                .WithParam("index", index)
                                .ExecuteWithoutResults();
                }
                scope.Complete();
            }
            Debug.WriteLine(j);
        }

        Debug.WriteLine(DateTime.Now.Subtract(t).Seconds);

public class Category
{
    public String label { get; set; }
}

根据 Chris Skardon 的说法,这些创建请求并未分批处理成几个 http 请求,而是每个请求都发送一个单独的请求(不确定它们是否共享所有一个 tx)。

对它们进行批处理更有效,例如将 10-50k 值放入列表中,并将其作为 "data" 参数发送到这样的密码语句:

UNWIND {data} as value CREATE (:TestItem {index: value});

或者如果您有多个属性,则创建一个字典列表作为参数

UNWIND {data} as row CREATE (:TestItem {index: row.index, foo: row.foo, bar: row.bar});

对于合并操作,您可以执行:

UNWIND {data} as row MERGE (t:TestItem {index: row.index}) ON CREATE SET  t.foo=row.foo, t.bar = row.bar;

甚至

UNWIND {data} as row MERGE (t:TestItem {index: row.index}) ON CREATE SET  t += row;

UNWIND {data} as row MERGE (t:TestItem {index: row.index}) ON CREATE SET  t += row.props;

基于 Michael 的回答 - 您要查看的代码是:

var client = new GraphClient(new Uri("http://localhost:7474/db/data"));
client.Connect();

var data = new List<Category>();
for (int i = 0; i < 20000; i++)
    data.Add(new Category { Label = i.ToString()});

DateTime t = DateTime.Now;
Debug.WriteLine(t);

for (int j = 0; j < 50; j++)
{
    client.Cypher
        .Unwind(data, "item")
        .Create("(:testItem { Label : item.Label })")
        .ExecuteWithoutResults();

    Debug.Write($"{j},");
}
Debug.WriteLine();
Debug.WriteLine($"Took {DateTime.Now.Subtract(t).Seconds} seconds");

这会在大约 21 秒内创建 100,000 个节点,当我尝试将 10,000 个节点重复 100 次时,需要 24 秒,因此调整批处理大小可能会产生不同的性能,我一次尝试了完整的 1,000,000 个节点- 大约需要 26 秒。无论哪种方式 - 比 900+ 秒好多了!