优化从python发出的cypher查询

时间:2018-03-28 17:45:15

标签: python neo4j cypher

driver for neo4j for python . I have a program that dynamically creates around 10-12 queries . The final result from all queries is collected in a list`并返回。

以下是10个此类查询:

MATCH  (sslc:subSubLocality)-[:CHILD_OF]->(v4)-[:CHILD_OF]->(v3)-[:CHILD_OF]->(v2)-[:CHILD_OF]->(st:state)  WHERE (st.name_wr = 'abcState') AND (sslc.name_wr= 'xyzSLC' OR sslc.name_wr= 'abcxyzcolony')  RETURN st, sslc, v4, v3, v2

MATCH  (slc:subLocality)-[:CHILD_OF]->(v3)-[:CHILD_OF]->(v2)-[:CHILD_OF]->(st:state)  WHERE (st.name_wr = 'abcState') AND (slc.name_wr= 'xyzSLC' OR slc.name_wr= 'abcxyzcolony')  RETURN st, slc, v3, v2

MATCH  (loc:locality)-[:CHILD_OF]->(v2)-[:CHILD_OF]->(st:state)  WHERE (st.name_wr = 'abcState') AND (loc.name_wr= 'deltax' OR loc.name_wr= 'xyzSLC' OR loc.name_wr= 'abcxyzcolony')  RETURN st, loc, v2

MATCH  (ct:city)-[:CHILD_OF]->(st:state)  WHERE (st.name_wr = 'abcState') AND (ct.name_wr= 'deltax' OR ct.name_wr= 'abcxyz')  RETURN st, ct

MATCH  (sslc:subSubLocality)-[:CHILD_OF]->(v3)-[:CHILD_OF]->(v2)-[:CHILD_OF]->(ct:city)  WHERE (ct.name_wr = 'deltax' OR ct.name_wr = 'abcxyz') AND (sslc.name_wr= 'xyzSLC' OR sslc.name_wr= 'abcxyzcolony')  RETURN ct, sslc, v3, v2

MATCH  (slc:subLocality)-[:CHILD_OF]->(v2)-[:CHILD_OF]->(ct:city)  WHERE (ct.name_wr = 'deltax' OR ct.name_wr = 'abcxyz') AND (slc.name_wr= 'xyzSLC' OR slc.name_wr= 'abcxyzcolony')  RETURN ct, slc, v2

MATCH  (loc:locality)-[:CHILD_OF]->(ct:city)  WHERE (ct.name_wr = 'deltax' OR ct.name_wr = 'abcxyz') AND (loc.name_wr= 'deltax' OR loc.name_wr= 'xyzSLC' OR loc.name_wr= 'abcxyzcolony')  RETURN ct, loc

MATCH  (sslc:subSubLocality)-[:CHILD_OF]->(v2)-[:CHILD_OF]->(loc:locality)  WHERE (loc.name_wr = 'deltax' OR loc.name_wr = 'xyzSLC' OR loc.name_wr = 'abcxyzcolony') AND (sslc.name_wr= 'xyzSLC' OR sslc.name_wr= 'abcxyzcolony')  RETURN loc, sslc, v2

MATCH  (slc:subLocality)-[:CHILD_OF]->(loc:locality)  WHERE (loc.name_wr = 'deltax' OR loc.name_wr = 'xyzSLC' OR loc.name_wr = 'abcxyzcolony') AND (slc.name_wr= 'xyzSLC' OR slc.name_wr= 'abcxyzcolony')  RETURN loc, slc

MATCH  (sslc:subSubLocality)-[:CHILD_OF]->(slc:subLocality)  WHERE (slc.name_wr = 'xyzSLC' OR slc.name_wr = 'abcxyzcolony') AND (sslc.name_wr= 'xyzSLC' OR sslc.name_wr= 'abcxyzcolony')  RETURN slc, sslc
  

查询可能会根据输入字典而改变(正如我之前提到的那样,查询是在运行时创建的)。但是查询共享相同的结构。

下面是我得到的Query Plan,它对于所有查询都保持不变,只是里面的值不同。

query 1

以下是我的代码,它会触发这些请求:

def get_query_response(query_list: list)-> list:
    driver = GraphDatabase.driver(uri, auth=("neo4j", "neo4j"))
    with driver.session() as session:
        with session.begin_transaction() as tx:
            response = [record.values() for query in query_list for record in tx.run(query)]
            return response

query_list是包含这些查询的str的集合。

问题是整个任务需要2秒才能给出回复。有没有办法优化查询或使其更快或可能在几毫秒内运行?

编辑:

回答几个问题:

  • 是的,提到的时间是获取结果所需的时间。我事先把它缩小了。
  • 查询大致从3ms - 10ms开始执行。当我在neo4j桌面上触发查询时。它是导致问题的驱动因素吗?
  • 是的,它是本地托管的neo4j数据库,我的系统是i7 16GB Memory with 1TB SSD
  • 不,我现在没有创建indeices而且我在500ms时遇到了性能提升但是现在1.5s我有什么方法可以推动它以毫秒为单位工作?

2 个答案:

答案 0 :(得分:1)

添加适当的indexesuniqueness constraints,以便您生成的查询无需扫描相应的节点即可开始工作。

例如(根据您的示例),您可以将索引添加到:

  • :subSubLocality(name_wr)
  • :subLocality(name_wr)
  • :locality(name_wr)
  • :city(name_wr)

答案 1 :(得分:0)

我无法确定原因是什么,但我有一些问题可以帮助我们更接近答案。

•您是否尝试过单独对这些查询进行基准测试?乍一看,它们看起来很简单,所以我认为这不是问题,但要知道你是否真的需要自己优化查询也不会有什么坏处。

•您提到它需要“2秒”,是从您点击“输入”以执行您的Python脚本的那一刻(因此包括启动与Neo4j实例的连接之类的事情),或者特别需要2.0秒要执行的查询?

•Neo4j v3.2之前的docs note that,Cypher计划者并不总能做出最有效的选择。如果您有早期版本,则文档提及您应该默认使用基于成本的计划程序。

•这是一个本地的Neo4j实例吗?如果托管,主机的硬件规格是什么?如果可能的话,可能不会伤害到规格。

•如果您尚未添加任何自定义indexing on properties,并且您的查询总是看起来一样,我建议您查看该选项。