Blueprints / Gremlin图表数据库查询本身是否缓慢?

时间:2014-08-27 17:14:53

标签: performance neo4j graph-databases gremlin titan

我正在研究使用GraphDB的概念证明(特别是HBase上的Titan 0.4.4)。为此,我创建了一个相对简单的图表:我有买卖产品的公司。销售与买方的部门相关联:

buyer {name} --BUYS {departmentId}--> product {name} <--SELLS-- seller {name}

我在图表中填写了1000个买家和卖家以及100万件产品。每种产品仅由一家公司出售,由1至6家公司随机选择的1至5个部门购买。所以我粗略地得到了100万个顶点和1150万个边缘。

现在我想查询以下内容的图表:返回名称与给定子字符串S匹配的所有产品,这些子字符串由名称为C的公司的D部门购买,我实现如下:

获取开始顶点:

start=graph.query().has("name", C).vertices()

由于我创建的顶点索引返回相对较快(在预热后<1ms)。现在我要运行相应的产品:

new GremlinPipeline(start).outE("BUYS").has("departmentId", D )
    .inV().has("name", new LowerCaseContainsPredicate(), P ).toList()

此针对HBase后端(AWS EMR上的10 m3.xlarge节点)的响应时间非常长,单个消费者平均每次查询约1.5秒(我选择了随机的买家,部门和产品名称以及迭代1000x),返回约260条产品记录。为了将可能有问题的HBase配置排除在等式之外,我将它运行在本地BerkelyDB上(4个CPU,8 GB VM内存,16 GB总内存)。

这加快了查询当然,在单线程应用程序中返回约160毫秒,这不是真正的赛车,但仍然可以接受。添加更多并行请求导致响应时间快速降低,平行请求中有10个并行请求。

所以我使用此Cypher查询与Neo4j 2.1.3进行了比较:

start buyer=node:company(name=C) match buyer-[:BUYS {departmentId:D}]->(product) 
where product.name =~ "(?i).*P.*" return product

返回速度更快(4-6倍取决于并行请求数,单线程约50毫秒,并行10个约270毫秒)。现在有一个针对Neo4j的Blueprints实现,所以我也尝试了一下,看看它是数据库引擎还是我查询的方式有所不同。

事实证明,针对Neo4j运行Gremlin查询的速度与对Titan一样慢 - 实际上它甚至会稍慢一些。

所有测试都作为Java应用程序在具有嵌入式图形DB的单个VM中运行,以避免任何网络影响。我还注意到第一个查询总是花费更长的时间,因此应用程序在开始基准测试之前首先运行随机查询。代码是使用GremlinePipeline Java类的纯Java,上面的代码段实际上是它运行的Java代码(谓词除外,它只实例化一次)。通过使用参数化常量查询字符串并传入相应的参数映射来运行Cypher查询。

这是我第一次使用图表数据库,因此我想知道我是否对Gremlin查询做了一些根本性的错误,或者Blueprints / Gremlin本质上是否很慢。

2 个答案:

答案 0 :(得分:1)

如果您使用的是Gremlin2,则不能混合Cypher和Gremlin,因为Gremlin使用自动索引,而Cypher使用新的“模式索引”。在Neo4j2 +中,自动索引已弃用/遗留。因此,在Gremlin3中,Gremlin利用与Cypher相同的指数。因此,如果您想要查看性能,请在两个Neo4jGraphs上进行测试。其数据填充了Gremlin,其数据填充了Cypher。然后,当正确使用索引时,您可以看到实际速度。

关于Titan / HBase。一定要打开缓存,否则你将永远转向磁盘(可能很热,但速度不如Titan的缓存)。请在这里阅读更多:    http://thinkaurelius.com/2013/11/24/boutique-graph-data-with-titan/

答案 1 :(得分:0)

问题的一个部分答案是我在Titan上缺少了以顶点为中心的指数,丹尼尔在评论中说。除了在我需要为我的BUYS标签创建索引的名称上创建顶点索引:

graph.makeKey("name").dataType(String.class).indexed(Vertex.class).make();

TitanKey departmentIndex=graph.makeKey("departmentId")
                         .dataType(String.class).make();
graph.makeLabel("BUYS").sortKey(departmentIndex).make();

Neo4j和Cypher仍然更快,显然这对Neo4j上的Gremlin查询没有影响,但这可能只是Neo4j的Gremlin实现的一个问题。