Neo4j性能与MySQL相比如何改进?

41

这是对《stackoverflow》上问题“无法重现/验证图形数据库和Neo4j在实际书籍中的性能要求”https://dev59.com/OnTYa4cB1Zd3GeqPx7eE的跟进。我已更新设置和测试,并且不想太大改动原问题。

整个故事(包括脚本等)可在https://baach.de/Members/jhb/neo4j-performance-compared-to-mysql找到。

简短版本:在试图验证《图形数据库》一书中所作的性能要求时,我得出了以下结果(查询包含n个人,每个人有50个朋友的随机数据集):

My results for 100k people

depth    neo4j             mysql       python

1        0.010             0.000        0.000
2        0.018             0.001        0.000
3        0.538             0.072        0.009
4       22.544             3.600        0.330
5     1269.942           180.143        0.758

"*": 仅限单次运行

My results for 1 million people

depth    neo4j             mysql       python

1        0.010             0.000        0.000
2        0.018             0.002        0.000
3        0.689             0.082        0.012
4       30.057             5.598        1.079
5     1441.397*          300.000        9.791

"*": 只运行一次

在64位Ubuntu上使用1.9.2版本,我已经设置了neo4j.properties文件中的这些值:

neostore.nodestore.db.mapped_memory=250M
neostore.relationshipstore.db.mapped_memory=2048M

使用neo4j-wrapper.conf中的:

wrapper.java.initmemory=1024
wrapper.java.maxmemory=8192

我的neo4j查询看起来是这样的(使用REST API):

start person=node:node_auto_index(noscenda_name="person123") match (person)-[:friend]->()-[:friend]->(friend) return count(distinct friend);

Node_auto_index已经就位,显然

我能做些什么来加速neo4j(使其比mysql更快)?

还有一个在Stackoverflow上的相同问题的另一个基准测试

2个回答

4

很抱歉您无法复制结果。但是,在MacBook Air上(1.8 GHz i7,4 GB RAM)使用2 GB堆、GCR缓存,但没有缓存预热和其他调整,并且使用类似大小的数据集(100万个用户,每人50个朋友),我在1.9.2上重复使用遍历框架大约需要900毫秒:

public class FriendOfAFriendDepth4
{
    private static final TraversalDescription traversalDescription = 
         Traversal.description()
            .depthFirst()
            .uniqueness( Uniqueness.NODE_GLOBAL )
            .relationships( withName( "FRIEND" ), Direction.OUTGOING )
            .evaluator( new Evaluator()
            {
                @Override
                public Evaluation evaluate( Path path )
                {
                    if ( path.length() >= 4 )
                    {
                        return Evaluation.INCLUDE_AND_PRUNE;
                    }
                    return Evaluation.EXCLUDE_AND_CONTINUE;

                }
            } );

    private final Index<Node> userIndex;

    public FriendOfAFriendDepth4( GraphDatabaseService db )
    {
        this.userIndex = db.index().forNodes( "user" );
    }

    public Iterator<Path> getFriends( String name )
    {
        return traversalDescription.traverse( 
            userIndex.get( "name", name ).getSingle() )
                .iterator();
    }

    public int countFriends( String name )
    {
        return  count( traversalDescription.traverse( 
            userIndex.get( "name", name ).getSingle() )
                 .nodes().iterator() );
    }
}

Cypher比您所认为的慢,但并不是非常慢: 大约3秒钟:

START person=node:user(name={name})
MATCH (person)-[:FRIEND]->()-[:FRIEND]->()-[:FRIEND]->()-[:FRIEND]->(friend)
RETURN count(friend)

敬祝好运

Ian


2
抱歉,在《Neo4j实战》中的场景是“返回所有朋友的朋友...”,而不是在给定的朋友之间查找路径。我指的是《Neo4j实战》第1章。SQL语句是关于查找所有朋友的,表格中的结果也是如此(返回的记录)。更重要的是:我绝对无法复制3秒钟的时间。例如查询 start person=node(100) match (person)-[:friend]->()-[:friend]->()-[:friend]->()-[:friend]->(friend) return count(friend); 需要28.9秒。非常奇怪... - Joerg Baach
3
是的,在1m个数据集上,使用MySQL找到两点A和B之间的路径需要大约2390毫秒,而在Neo4j上只需要大约25毫秒。 - Joerg Baach
Neo4j展示了它在查询关系(路径)而不是节点时的强大能力,对吧? - Emma He

3

是的,我认为 REST API 比常规绑定要慢得多,这就是你的性能问题所在。


好的观点。是的,我想你运行嵌入式与独立(使用过程/插件)会得到不同的结果。 - yngwietiger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接