(Neo4j 非托管扩展 API) 为啥查询的速度取决于 Neo4j 中数据集的大小?

Posted

技术标签:

【中文标题】(Neo4j 非托管扩展 API) 为啥查询的速度取决于 Neo4j 中数据集的大小?【英文标题】:(Neo4j Unmanaged extension API) Why the speed of query depends on the size of dataset in Neo4j?(Neo4j 非托管扩展 API) 为什么查询的速度取决于 Neo4j 中数据集的大小? 【发布时间】:2016-09-17 16:47:29 【问题描述】:

我正在尝试为 Neo4j 服务器(社区版)构建一个简单的非托管扩展。

我有同一个数据集的多个版本(一个有 11k 节点的小版本,一个有 85k 节点的大版本)。小号是大号的子集。我的节点有一个“id”属性,它不是neo4j 的,而是另一个名为“id”的属性。我在小数据集中选择一个节点的 id 并在每个数据集中运行以下查询:

    从id中获取节点 获取所有节点的关系

我这样做了几次以消除速度测量过程中的一些噪音。代码是:

@Path("/test")
public class QueryTest 
    private GraphDatabaseService graphdb;

    public QueryTest (@Context GraphDatabaseService graphdb) 
        this.graphdb = graphdb;
    

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response test(final @QueryParam("any") List<Long> any, final @QueryParam("iter") int iter)
        JsonGenerator result = new JsonGenerator();

        result.writeStartObject();
        result.writeKeyValue("iteration", iter);
        result.writeKey("time");
        result.writeStartArray();

        ListIterator<Long> it = any.listIterator();

        long id;
        long startTime, stopTime, mean = 0;
        Node node;
        int i = 0;

        try(Transaction tx = graphdb.beginTx()) 
            while (it.hasNext()) 
                id = it.next();
                while (i++ < iter) 
                    startTime = System.nanoTime();
                    node = graphdb.findNode(Label.label("Movie"), "id", id);
                    Iterable<Relationship> t = node.getRelationships();
                    stopTime = System.nanoTime();
                    mean += (stopTime - startTime);
                
                result.writeLong(mean / iter);
            
            tx.success();
        
        result.writeEndArray();
        result.writeEndObject();
        return Response.status(Status.OK).entity(result.getJson()).build();
    

其中 JsonGenerator 是 Json 创建者类。

使用 Get 方法访问数据库时,它在小数据集上运行大约 0.65 到 0.7ms,在较大数据集上运行大约 10ms。

这对我来说似乎很奇怪,是否真的需要 10 倍以上的时间才能找到一个节点或其关系?我在一个更大的项目中使用它,我不希望数据集的大小影响性能(这就是我选择面向图形的数据库的原因)。我已阅读有关非托管扩展的文档:

这是一个利器,允许用户部署任意JAX-RS 类到服务器,所以使用它时要小心。尤其 很容易消耗服务器上的大量堆空间并降级 表现。如有疑问,请通过社区之一寻求帮助 渠道。

会不会是我的问题?是不是因为不清除事务中的任何内容而消耗了太多堆?任何人都有一个想法,或者可能只是对前面的引用有一些看法,特别是为什么很容易消耗太多堆?

谢谢

【问题讨论】:

【参考方案1】:

如果您没有在标签/属性组合上创建索引,那么 neo4j 必须遍历每个节点并检查其id 属性。如果你索引它,它可以通过逆过程(知道id属性,它可以找到所有对应的节点),这使得它更快,并且不再依赖于数据库大小。

见this.

【讨论】:

谢谢托雷。它似乎工作。你知道为什么堆可能被太多使用..吗? (在另一种情况下)我只是好奇.. 通常当堆爆炸时,这是因为您的查询中的一个步骤生成了太多行,这通常是查询未索引属性的症状(创建一个查询步骤,使一行对于每个节点,然后删除与属性条件不匹配的行)。它也可能是堆叠 MATCH 查询的结果,其中对第一个 MATCH 的每个响应对应于第二个 MATCH 的每个响应都会获得一行,从而使您的行数呈指数增长。分析您的查询,看看它真正的爆发点。 我没有过多地使用扩展,但我认为它们存在的堆危险是存储过程中的逻辑从查询分析中掩盖了它的性能特征,因此用户可能会导致问题并且无法找出原因。 谢谢,有道理!

以上是关于(Neo4j 非托管扩展 API) 为啥查询的速度取决于 Neo4j 中数据集的大小?的主要内容,如果未能解决你的问题,请参考以下文章

Neo4j的查询速度为何这么慢?这能商用吗

为啥访问非托管内存会导致 System.AccessViolationException? [复制]

为啥我在postgresql的json数据中查询,速度会比mysql慢很多

Oracle中,为啥同样的SELECT查询语句,加了CREATE TABLE AS后速度更快了?

为啥我在postgresql的json数据中查询,速度会比mysql慢很多

Elasticsearch:ES 倒排索引为啥查询速度会这么快