使用Neo4jClient减慢创建时间

时间:2016-04-09 20:06:35

标签: c# .net neo4j neo4jclient

我是Neo4j和Neo4jClient的新手。

我正在尝试为简单操作获得一些基准。 我似乎得到了非常慢的插入(CREATEs)。 我认识到这不是进行批量插入的最快方法,但它更能反映我的应用程序在现实生活中的表现。

目标:添加一个Person对象并将其链接到“超级用户/人”

设置

  1. 在Neo4j控制台中,我创建了一个人并将“myId”字段编入索引
  2. 我正在运行带有8g RAM的I5 MS SurfaceBook。 Windows 10。
  3. Visual Studio 2015社区,更新2 RC2
  4. 结果:添加每100个用户和关系需要7秒钟。这是来自秒表的一些计时数据:
    增加了200人。经过时间= 00:00:35.5526979
    增加了300人。经过时间= 00:00:43.7953471
    增加了400人。经过时间= 00:00:51.0138293
    增加了400人。经过时间= 00:00:51.0139585
    新增500人。经过时间= 00:00:56.0563539
    增加了700人。经过时间= 00:01:03.5407927
    增加了800人。经过时间= 00:01:08.0186756
    新增900人。经过时间= 00:01:13.0089620
    新增900人。经历时间= 00:01:13.0089809

    代码:这看起来非常简单。我只有一个创建新人的循环,然后创建关系:

            //Create SuperNode
            int supermyId = 4000;// Guid.NewGuid().GetHashCode();
            Person superPerson1 = new Person { name = "SUPER Name5 99900", born = 1903, myId = supermyId };
    
            int regularId = 0;
            Person regularPerson = null;
    
            graphClient.Cypher
                .Create("(person:Person {newUser})")
                .WithParam("newUser", superPerson1)
                .ExecuteWithoutResults();
    
            sw.Start();
            Parallel.For( 0, 5000, 
                index => {
                    regularId ++;
                    regularPerson = new Person() { name = "regular5 " + regularId, born = 1000, myId = regularId };
                    graphClient.Cypher
                        .Create("(person:Person {regularPerson})")
                        .WithParam("regularPerson", regularPerson)
                        .ExecuteWithoutResults();
    
                    graphClient.Cypher
                    .Match("(superUser:Person)", "(regularUser:Person)")
                    .Where((Person superUser) => superUser.myId == supermyId)
                    .AndWhere((Person regularUser) => regularUser.myId == regularId)
                    .Create("regularUser-[:SUPER5]->superUser")
                    .ExecuteWithoutResults();
                    if (regularId % 100 == 0)
                    {
                        Console.WriteLine("Added " + regularId + " Persons. Elapsed time = " + sw.Elapsed);
                    }
                });
    

    问题

    1. 对于这些操作,这看起来是正常速度吗?
    2. 有关如何加快速度的想法吗?

1 个答案:

答案 0 :(得分:0)

因此,这取决于您如何创建节点,最好的方法是首先一次创建regularPerson个节点:

var regularPersons = new List<Person>();
for(int i = 0; i < 5000; i++)
{
    //Generate users here
}

并使用Unwind关键字将其传递给Neo4j。这允许您传入整个集合。

现在,您正在做的另一件事是每次添加都会运行两个查询 - 一个用于添加人员,两个用于加入superUser,我们可以将其压缩为一个查询,这将更快地运行

所以,(我没有在计算机上输入此内容,因此请原谅错误),在一个查询中创建superUser,然后:

graphClient.Cypher
    .Match("(su:Person)")
    .Where((Person su) => su.myId == supermyId)
    .Unwind(regularPersons, "rp")
    .Create("(p:Person {rp})-[:SUPER5]->(su)")
    .ExecuteWithoutResults();

正如我所说 - 我目前无法对此进行测试,但请稍稍旋转并进行一些实验,看看它是如何工作的,一般来说, 应该看到这会生成5000 a比你拥有它快得多。

这是我的工作代码,在1.3秒内添加5000个节点:

void Main()
{
    var graphClient = new GraphClient(new Uri("http://localhost.:7474/db/data/"));
    graphClient.Connect();

    var supermyId = 4000;
    Person superPerson1 = new Person { name = "SUPER Name5 99900", born = 1903, myId = supermyId };

    graphClient.Cypher
            .Create("(person:Person {newUser})")
            .WithParam("newUser", superPerson1)
            .ExecuteWithoutResults();

    var regularPersons = new List<Person>();
    for (int i = 0; i < 5000; i++)
    {
        regularPersons.Add(new Person { name = $"Person_{i}", born = 1900+(i%100), myId = i + 4000 });
    }

    var now = DateTime.Now;
    graphClient.Cypher
        .Match("(su:Person)")
        .Where((Person su) => su.myId == supermyId)
        .Unwind(regularPersons, "rp")
        .Create("(p:Person {born: rp.born, myId: rp.myId, name:rp.name})-[:SUPER5]->(su)")

        .ExecuteWithoutResults();

    Console.WriteLine($"Took {(DateTime.Now - now)} to add");
}

public class Person
{
    public int myId { get; set;}
    public int born { get;set; }
    public string name { get; set; }
}