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+ 秒好多了!
我正在尝试使用 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+ 秒好多了!