优化Cypher查询的性能

时间:2015-09-21 03:01:07

标签: neo4j

这是我上一个问题的后续问题:Correct way to create json from neo4j rest API

我能够通过@Michael Hunger提供给我的帮助,以我所要求的格式获得JSON。以下是代码:

    MATCH (mainCap:Capability{SectorID:"PNU"})  
    OPTIONAL MATCH  (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)    
    OPTIONAL MATCH  (adoptsCap1)-[r2:KPI_Capability]->(capKPI)
    OPTIONAL MATCH  (adoptsCap1)-[r4:Capability_Capability]->(cap1)         
    OPTIONAL MATCH (cap1)<-[r5:Capability_Capability]-(isPart1)
    OPTIONAL MATCH (cap1)-[r6:KPI_Capability]->(KPI1)
    OPTIONAL MATCH (cap1)-[r7:Capability_Capability]->(cap2)
    OPTIONAL MATCH (cap2)<-[r8:Capability_Capability]-(isPart2)
    OPTIONAL MATCH (cap2)-[r9:KPI_Capability]->(KPI2)
    OPTIONAL MATCH (cap2)-[r10:Capability_Capability]->(cap3)
    OPTIONAL MATCH (cap3)<-[r11:Capability_Capability]-(isPart3)
    OPTIONAL MATCH (cap3)-[r12:KPI_Capability]->(KPI3)

    OPTIONAL MATCH (mainCap)<-[r3:Capability_Capability]-(isPart:Capability)                                                                                                        
    with
        mainCap as mainCap, 
        isPart as isPart,
        adoptsCap1 as adoptsCap1,
        cap1 as cap1,
        cap2 as cap2,
        cap3 as cap3,
        KPI2 as KPI2,
        isPart2 as isPart2,
        KPI1 as KPI1,
        isPart1 as isPart1,
        capKPI as capKPI,
        CASE WHEN KPI3 IS NOT NULL THEN
        COLLECT(DISTINCT
          {
            _id: KPI3.ExternalID,
            type: labels(KPI3)[0],
            name: KPI3.Name,
            description: KPI3.Description,
            sectorID: KPI3.SectorID,
            CCO: KPI3.CCO,
            CFO: KPI3.CFO,
            SVPHR: KPI3.SVPHR,
            area: KPI3.Area,
            CEO: KPI3.CEO,
            CIO: KPI3.CIO,
            COO: KPI3.COO       
          }
        )
      ELSE
        []
        END as cpbltyIsMsrdByKpiPttrn3,

        CASE WHEN isPart3 IS NOT NULL THEN
            COLLECT(DISTINCT
              {
              _id: isPart3.ExternalID,
                type: labels(isPart3)[0]                        
              }
            )
          ELSE
            []
            END as isPartOfCapability3      

                    with

                    mainCap as mainCap, 
                    isPart as isPart,
                    adoptsCap1 as adoptsCap1,
                    cap1 as cap1,
                    cap2 as cap2,                   
                    KPI1 as KPI1,
                    isPart1 as isPart1,
                    capKPI as capKPI,
                    CASE WHEN cap3 IS NOT NULL THEN
                    COLLECT(DISTINCT
                      {
                      _id: cap3.ExternalID,
                        type: labels(cap3)[0],
                        name: cap3.Name,
                        description: cap3.Overview,
                        sectorID: cap3.SectorID,
                        cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn3,
                        isPartOfCapability:isPartOfCapability3
                      }
                    )
                  ELSE
                    []
                    END as consistsOfCapability3,           


                    CASE WHEN KPI2 IS NOT NULL THEN
                    COLLECT(DISTINCT
                      {
                        _id: KPI2.ExternalID,
                        type: labels(KPI2)[0],
                        name: KPI2.Name,
                        description: KPI2.Description,
                        sectorID: KPI2.SectorID,
                        CCO: KPI2.CCO,
                        CFO: KPI2.CFO,
                        SVPHR: KPI2.SVPHR,
                        area: KPI2.Area,
                        CEO: KPI2.CEO,
                        CIO: KPI2.CIO,
                        COO: KPI2.COO       
                      }
                    )
                  ELSE
                    []
                    END as cpbltyIsMsrdByKpiPttrn2,

                    CASE WHEN isPart2 IS NOT NULL THEN
                        COLLECT(DISTINCT
                          {
                          _id: isPart2.ExternalID,
                            type: labels(isPart2)[0]                        
                          }
                        )
                      ELSE
                        []
                        END as isPartOfCapability2              

                            with mainCap as mainCap,
                                adoptsCap1 as adoptsCap1,
                                isPart as isPart,
                                cap1 as cap1,                               
                                capKPI as capKPI,
                            CASE WHEN cap2 IS NOT NULL THEN
                            COLLECT(DISTINCT
                              {
                              _id: cap2.ExternalID,
                                type: labels(cap2)[0],
                                name: cap2.Name,
                                description: cap2.Overview,
                                sectorID: cap2.SectorID,
                                cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn2,
                                isPartOfCapability:isPartOfCapability2,
                                consistsOfCapability:consistsOfCapability3
                              }
                            )
                          ELSE
                            []
                            END as consistsOfCapability2,                   


                            CASE WHEN KPI1 IS NOT NULL THEN
                            COLLECT(DISTINCT
                              {
                                _id: KPI1.ExternalID,
                                type: labels(KPI1)[0],
                                name: KPI1.Name,
                                description: KPI1.Description,
                                sectorID: KPI1.SectorID,
                                CCO: KPI1.CCO,
                                CFO: KPI1.CFO,
                                SVPHR: KPI1.SVPHR,
                                area: KPI1.Area,
                                CEO: KPI1.CEO,
                                CIO: KPI1.CIO,
                                COO: KPI1.COO           
                              }
                            )
                          ELSE
                            []
                            END as cpbltyIsMsrdByKpiPttrn1,

                            CASE WHEN isPart1 IS NOT NULL THEN
                                COLLECT(DISTINCT
                                  {
                                  _id: isPart1.ExternalID,
                                    type: labels(isPart1)[0]                        
                                  }
                                )
                              ELSE
                                []
                                END as isPartOfCapability1  

                                    with mainCap as mainCap,
                                    adoptsCap1 as adoptsCap1,
                                    isPart as isPart,
                                    CASE WHEN cap1 IS NOT NULL THEN
                                    COLLECT(DISTINCT
                                      {
                                      _id: cap1.ExternalID,
                                        type: labels(cap1)[0],
                                        name: cap1.Name,
                                        description: cap1.Overview,
                                        sectorID: cap1.SectorID,
                                        cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn1,
                                        isPartOfCapability:isPartOfCapability1,
                                        consistsOfCapability:consistsOfCapability2
                                      }
                                    )
                                    ELSE
                                    []
                                    END as consistsOfCapability1,

                                    CASE WHEN capKPI IS NOT NULL THEN
                                        COLLECT(DISTINCT
                                          {
                                            _id: capKPI.ExternalID,
                                            type: labels(capKPI)[0],
                                            name: capKPI.Name,
                                            description: capKPI.Description,
                                            sectorID: capKPI.SectorID,
                                            CCO: capKPI.CCO,
                                            CFO: capKPI.CFO,
                                            SVPHR: capKPI.SVPHR,
                                            area: capKPI.Area,
                                            CEO: capKPI.CEO,
                                            CIO: capKPI.CIO,
                                            COO: capKPI.COO 
                                          }
                                        )
                                      ELSE
                                        []
                                        END as cpbltyIsMsrdByKpiPttrn

        return {
                        _id:mainCap.ExternalID, 
                        type:labels(mainCap)[0],
                        name:mainCap.Name,
                        adoptsCapability: 

                                CASE WHEN adoptsCap1 IS NOT NULL THEN
                                                COLLECT(DISTINCT
                                                  {
                                                    _id: adoptsCap1.ExternalID,
                                                    type: labels(adoptsCap1)[0],
                                                    name: adoptsCap1.Name,
                                                    description: adoptsCap1.Overview,
                                                    sectorID: adoptsCap1.SectorID,
                                                    cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn,
                                                    consistsOfCapability:consistsOfCapability1                                                  
                                                  }
                                                )
                                                ELSE
                                                []
                                                END,
                        isPartOfCapability:             
                                CASE WHEN isPart IS NOT NULL THEN
                                            COLLECT(DISTINCT
                                              {
                                              _id: isPart.ExternalID,
                                                type: labels(isPart)[0]                     
                                              }
                                            )
                                          ELSE
                                            []
                                            END 



        }as `col2`

以上查询采用 4149 ms 来提供结果。我尝试使用distinct进行优化。通过: http://thought-bytes.blogspot.com/2013/01/optimizing-neo4j-cypher-queries.htmlOptimize Neo4j Cypher query 更相关:Optimizing Cypher queries with lots of optional relationships

问题:是否可以优化并将时间缩短到约2秒左右?我有一个angularjs UI,它有一个菜单绑定来自neo的数据。它目前需要4.4秒才能从neo获取数据或者这是我可以从这个查询中获得的最大性能吗?

以下是我的执行计划: enter image description here

帮助表示感谢。谢谢

以下是解决方案:

重新格式化查询后,性能大幅提升。基数导致性能滞后。 从4149毫秒下降到400毫秒

    match (mainCap:Capability{SectorID:"PNU"}) 
                OPTIONAL MATCH  (mainCap:Capability)-[r1:CapabilityAdopts_Capability]->(adoptsCap1) 
                                            OPTIONAL MATCH  (adoptsCap1)-[r2:KPI_Capability]->(capKPI)
                                            OPTIONAL MATCH  (adoptsCap1)-[r4:Capability_Capability]->(cap1) 

                                            with mainCap, adoptsCap1, cap1,
                                            CASE WHEN capKPI IS NOT NULL THEN
                                        COLLECT(DISTINCT
                                          {
                                            _id: capKPI.ExternalID,
                                            type: labels(capKPI)[0],
                                            name: capKPI.Name,
                                            description: capKPI.Description,
                                            sectorID: capKPI.SectorID,
                                            CCO: capKPI.CCO,
                                            CFO: capKPI.CFO,
                                            SVPHR: capKPI.SVPHR,
                                            area: capKPI.Area,
                                            CEO: capKPI.CEO,
                                            CIO: capKPI.CIO,
                                            COO: capKPI.COO 
                                          }
                                        )
                                      ELSE
                                        []
                                        END as cpbltyIsMsrdByKpiPttrn


                                        OPTIONAL MATCH (cap1)<-[r5:Capability_Capability]-(isPart1)
                                        OPTIONAL MATCH (cap1)-[r6:KPI_Capability]->(KPI1)
                                        OPTIONAL MATCH (cap1)-[r7:Capability_Capability]->(cap2)

                                        with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cap2,
                                            CASE WHEN KPI1 IS NOT NULL THEN
                                            COLLECT(DISTINCT
                                              {
                                                _id: KPI1.ExternalID,
                                                type: labels(KPI1)[0],
                                                name: KPI1.Name,
                                                description: KPI1.Description,
                                                sectorID: KPI1.SectorID,
                                                CCO: KPI1.CCO,
                                                CFO: KPI1.CFO,
                                                SVPHR: KPI1.SVPHR,
                                                area: KPI1.Area,
                                                CEO: KPI1.CEO,
                                                CIO: KPI1.CIO,
                                                COO: KPI1.COO           
                                              }
                                            )
                                          ELSE
                                            []
                                            END as cpbltyIsMsrdByKpiPttrn1,

                                            CASE WHEN isPart1 IS NOT NULL THEN
                                                COLLECT(DISTINCT
                                                  {
                                                  _id: isPart1.ExternalID,
                                                    type: labels(isPart1)[0]                        
                                                  }
                                                )
                                              ELSE
                                                []
                                                END as isPartOfCapability1  


                                        OPTIONAL MATCH (cap2)<-[r8:Capability_Capability]-(isPart2)
                                        OPTIONAL MATCH (cap2)-[r9:KPI_Capability]->(KPI2)
                                        OPTIONAL MATCH (cap2)-[r10:Capability_Capability]->(cap3)

                                        with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cap2,cpbltyIsMsrdByKpiPttrn1,isPartOfCapability1,cap3,

                                        CASE WHEN KPI2 IS NOT NULL THEN
                                        COLLECT(DISTINCT
                                          {
                                            _id: KPI2.ExternalID,
                                            type: labels(KPI2)[0],
                                            name: KPI2.Name,
                                            description: KPI2.Description,
                                            sectorID: KPI2.SectorID,
                                            CCO: KPI2.CCO,
                                            CFO: KPI2.CFO,
                                            SVPHR: KPI2.SVPHR,
                                            area: KPI2.Area,
                                            CEO: KPI2.CEO,
                                            CIO: KPI2.CIO,
                                            COO: KPI2.COO       
                                          }
                                        )
                                      ELSE
                                        []
                                        END as cpbltyIsMsrdByKpiPttrn2,

                                        CASE WHEN isPart2 IS NOT NULL THEN
                                            COLLECT(DISTINCT
                                              {
                                              _id: isPart2.ExternalID,
                                                type: labels(isPart2)[0]                        
                                              }
                                            )
                                          ELSE
                                            []
                                            END as isPartOfCapability2

                                        OPTIONAL MATCH (cap3)<-[r11:Capability_Capability]-(isPart3)                                                                                                                                    
                                        OPTIONAL MATCH (cap3)-[r12:KPI_Capability]->(KPI3)

                                        with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cap2,cpbltyIsMsrdByKpiPttrn1,isPartOfCapability1,cpbltyIsMsrdByKpiPttrn2,isPartOfCapability2,cap3,

                                        CASE WHEN KPI3 IS NOT NULL THEN
                                        COLLECT(DISTINCT
                                          {
                                            _id: KPI3.ExternalID,
                                            type: labels(KPI3)[0],
                                            name: KPI3.Name,
                                            description: KPI3.Description,
                                            sectorID: KPI3.SectorID,
                                            CCO: KPI3.CCO,
                                            CFO: KPI3.CFO,
                                            SVPHR: KPI3.SVPHR,
                                            area: KPI3.Area,
                                            CEO: KPI3.CEO,
                                            CIO: KPI3.CIO,
                                            COO: KPI3.COO       
                                          }
                                        )
                                      ELSE
                                        []
                                        END as cpbltyIsMsrdByKpiPttrn3,

                                        CASE WHEN isPart3 IS NOT NULL THEN
                                            COLLECT(DISTINCT
                                              {
                                              _id: isPart3.ExternalID,
                                                type: labels(isPart3)[0]                        
                                              }
                                            )
                                          ELSE
                                            []
                                            END as isPartOfCapability3  



                                        with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cap2,cpbltyIsMsrdByKpiPttrn1,isPartOfCapability1,cpbltyIsMsrdByKpiPttrn2,isPartOfCapability2,

                                        CASE WHEN cap3 IS NOT NULL THEN
                                        COLLECT(DISTINCT
                                          {
                                          _id: cap3.ExternalID,
                                            type: labels(cap3)[0],
                                            name: cap3.Name,
                                            description: cap3.Overview,
                                            sectorID: cap3.SectorID,
                                            cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn3,
                                            isPartOfCapability:isPartOfCapability3
                                          }
                                        )
                                      ELSE
                                        []
                                        END as consistsOfCapability3


                                    with mainCap, adoptsCap1, cap1,cpbltyIsMsrdByKpiPttrn,cpbltyIsMsrdByKpiPttrn1,isPartOfCapability1,

                                    CASE WHEN cap2 IS NOT NULL THEN
                                    COLLECT(DISTINCT
                                      {
                                      _id: cap2.ExternalID,
                                        type: labels(cap2)[0],
                                        name: cap2.Name,
                                        description: cap2.Overview,
                                        sectorID: cap2.SectorID,
                                        cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn2,
                                        isPartOfCapability:isPartOfCapability2,
                                        consistsOfCapability:consistsOfCapability3
                                      }
                                    )
                                  ELSE
                                    []
                                    END as consistsOfCapability2

                                    with mainCap, adoptsCap1, cpbltyIsMsrdByKpiPttrn,

                                    CASE WHEN cap1 IS NOT NULL THEN
                                    COLLECT(DISTINCT
                                      {
                                      _id: cap1.ExternalID,
                                        type: labels(cap1)[0],
                                        name: cap1.Name,
                                        description: cap1.Overview,
                                        sectorID: cap1.SectorID,
                                        cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn1,
                                        isPartOfCapability:isPartOfCapability1,
                                        consistsOfCapability:consistsOfCapability2
                                      }
                                    )
                                    ELSE
                                    []
                                    END as consistsOfCapability1


OPTIONAL MATCH (mainCap)<-[r3:Capability_Capability]-(isPart:Capability)

return {
model:{ 

    _id:mainCap.ExternalID, 
    type:labels(mainCap)[0],
    name:mainCap.Name,

    adoptsCapability: 

            CASE WHEN adoptsCap1 IS NOT NULL THEN
                            COLLECT(DISTINCT
                              {
                                _id: adoptsCap1.ExternalID,
                                type: labels(adoptsCap1)[0],
                                name: adoptsCap1.Name,
                                description: adoptsCap1.Overview,
                                sectorID: adoptsCap1.SectorID,
                                cpbltyIsMsrdByKpiPttrn:cpbltyIsMsrdByKpiPttrn,
                                consistsOfCapability:consistsOfCapability1

                              }
                            )
                            ELSE
                            []
                            END,

                            isPartOfCapability:             
                                CASE WHEN isPart IS NOT NULL THEN
                                            COLLECT(DISTINCT
                                              {
                                              _id: isPart.ExternalID,
                                                type: labels(isPart)[0]                     
                                              }
                                            )
                                          ELSE
                                            []
                                            END 




    }

}

2 个答案:

答案 0 :(得分:1)

添加约束或索引

用于您的起始节点:

CREATE CONSTRAINT ON (mainCap:Capability) assert mainCap.SectorID IS UNIQUE;

CREATE INDEX ON :Capability(SectorID);

减少基数

最重要的一点是让你的中间基数降低。

否则,前一个语句产生的每一行都会重复匹配,无论它是否是重复的行。

MATCH (mainCap:Capability{SectorID:"PNU"})  
    OPTIONAL MATCH  (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)-[r2:KPI_Capability]->(capKPI),
    OPTIONAL MATCH  (adoptsCap1)-[r4:Capability_Capability]->(cap1)         
// reduce cardinality
with mainCap, adoptsCap1, cap1, collect(distinct capKPI) as _capKPI
    OPTIONAL MATCH (cap1)<-[r5:Capability_Capability]-(isPart1)
with mainCap,  adoptsCap1, cap1, _capKPI, collect(isPart1) as _isPart1
...

PS如果名称没有像mainCap as mainCap,

那样改变,则不需要别名

并尝试从顶部开始,随时进行剖析。

答案 1 :(得分:0)

根据您使用的Neo4j版本(在2.2.0之前或之后),尝试快速尝试:

尝试合并所有OPTIONAL MATCH条款,如下所示:

MATCH (mainCap:Capability{SectorID:"PNU"})  
OPTIONAL MATCH
  (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1),
  (adoptsCap1)-[r2:KPI_Capability]->(capKPI),
  (adoptsCap1)-[r4:Capability_Capability]->(cap1),
  (cap1)<-[r5:Capability_Capability]-(isPart1),
  (cap1)-[r6:KPI_Capability]->(KPI1),
  (cap1)-[r7:Capability_Capability]->(cap2),
  (cap2)<-[r8:Capability_Capability]-(isPart2),
  (cap2)-[r9:KPI_Capability]->(KPI2),
  (cap2)-[r10:Capability_Capability]->(cap3),
  (cap3)<-[r11:Capability_Capability]-(isPart3),
  (cap3)-[r12:KPI_Capability]->(KPI3),

  (mainCap)<-[r3:Capability_Capability]-(isPart:Capability)

而不是:

MATCH (mainCap:Capability{SectorID:"PNU"})  
OPTIONAL MATCH  (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)    
OPTIONAL MATCH  (adoptsCap1)-[r2:KPI_Capability]->(capKPI)
OPTIONAL MATCH  (adoptsCap1)-[r4:Capability_Capability]->(cap1)         
OPTIONAL MATCH (cap1)<-[r5:Capability_Capability]-(isPart1)
OPTIONAL MATCH (cap1)-[r6:KPI_Capability]->(KPI1)
OPTIONAL MATCH (cap1)-[r7:Capability_Capability]->(cap2)
OPTIONAL MATCH (cap2)<-[r8:Capability_Capability]-(isPart2)
OPTIONAL MATCH (cap2)-[r9:KPI_Capability]->(KPI2)
OPTIONAL MATCH (cap2)-[r10:Capability_Capability]->(cap3)
OPTIONAL MATCH (cap3)<-[r11:Capability_Capability]-(isPart3)
OPTIONAL MATCH (cap3)-[r12:KPI_Capability]->(KPI3)

OPTIONAL MATCH (mainCap)<-[r3:Capability_Capability]-(isPart:Capability)

修改

我没有仔细阅读查询,因为我打算打电话,但你也可以将它们组合起来:

OPTIONAL MATCH  (mainCap)-[r1:CapabilityAdopts_Capability]->(adoptsCap1)-[r2:KPI_Capability]->(capKPI)

Neo4j非常聪明,无论如何都能很好地处理它,所以它是一种风格选择。