2014-09-04 3 views
1

최근에는 그래프 데이터베이스와 Neo4j로 시작했습니다. Person, Company, City, Skill 사이에 하나 이상의 관계가있는 노드를 만들었습니다.Cypher 쿼리 성능 및 구조

하나의 Person 노드를 (노드 ID로) 찾은 다음이 사람과 관련된 모든 기술, 회사 등을 찾고자하는 사이퍼 쿼리를 수행하려고합니다. 이것은 지금까지 내 쿼리입니다 :

MATCH (person:Person) 
WHERE ID (person) = 123 
WITH person LIMIT 1 
OPTIONAL MATCH (p:Person) - [:HAS_SKILL] -> (skill:Skill) 
WHERE ID (p) = 123 
WITH person, skill ORDER BY skill.name ASC 
OPTIONAL MATCH (p:Person) - [:WORKED_AT] -> (company:Company) 
WHERE ID (p) = 123 
WITH person, skill, company ORDER BY company.name ASC 
OPTIONAL MATCH (p:Person) - [:LIVES_IN] -> (city:City) 
WHERE ID (p) = 123 
WITH person 
, collect(DISTINCT skill) as skills 
, collect(DISTINCT company) as companies 
, city LIMIT 1 
RETURN person, skills, companies, city 

나는 이것이 정말 최적의 쿼리 아니라고 걱정하고/우리가 얻을 때 만 개 노드의 몇 가지를 말할 수 있다면 정말 느린 것처럼 보인다. 누군가가 이런 종류의 쿼리를 구조화하는 더 좋은 방법을 말해 줄 수 있습니까? 여러 개의 작은 쿼리로 나눠야합니까?

답변

2

먼저 변수가 이미 바인딩되어 있으므로 성능에 영향을 미치지 않을지라도 person 객체를 계속 쿼리 할 필요가 없다고 생각합니다. 즉 당신의 쿼리를 감소 : 또한 여러 MATCH 문을 가질 수 있습니다으로 WITH를 계속 사용할 필요가 없습니다

MATCH (person:Person) 
WHERE ID (person) = 123 
WITH person 
OPTIONAL MATCH (person) - [:HAS_SKILL] -> (skill:Skill) 
WITH person, skill ORDER BY skill.name ASC 
OPTIONAL MATCH (person) - [:WORKED_AT] -> (company:Company) 
WITH person, skill, company ORDER BY company.name ASC 
OPTIONAL MATCH (person) - [:LIVES_IN] -> (city:City) 
WITH person 
, collect(DISTINCT skill) as skills 
, collect(DISTINCT company) as companies 
, city LIMIT 1 
RETURN person, skills, companies, city 

,하지만 지금 주문 문 제거한 :

MATCH (person:Person) 
WHERE ID (person) = 123 
OPTIONAL MATCH (person) - [:HAS_SKILL] -> (skill:Skill) 
OPTIONAL MATCH (person) - [:WORKED_AT] -> (company:Company) 
OPTIONAL MATCH (person) - [:LIVES_IN] -> (city:City) 
RETURN person 
, collect(DISTINCT skill) as skills 
, collect(DISTINCT company) as companies 
, city LIMIT 1 

내가 생각을 당신은 더 이런 주문할 수 있습니다,하지만 당신은 더 이상 확대됨에, 당신이해야 테스트하는 것입니다 여부 이상한 정렬 순서! :

MATCH (person:Person) 
WHERE ID (person) = 123 
OPTIONAL MATCH (person) - [:HAS_SKILL] -> (skill:Skill) 
OPTIONAL MATCH (person) - [:WORKED_AT] -> (company:Company) 
OPTIONAL MATCH (person) - [:LIVES_IN] -> (city:City) 
WITH DISTINCT person, skill, company, city 
ORDER BY skill.name, company.name 
RETURN person 
, collect(DISTINCT skill) as skills 
, collect(DISTINCT company) as companies 
, city LIMIT 1 

로 끝날 것입니다. 한계를 설정하거나 집계하려면 WITH 문을 원래대로 사용해야합니다.

그냥 직접 관련이없는 마크 니드 햄에 의해 최적화이 blog post을 기억하지만 다시 언급 가치가있는 몇 가지 규칙이 포함되어 때마다 당신이 할 수

  1. 를 사용하여 매개 변수를.
  2. 필요한 데이터를 가져올 필요가없는 경우 직교 제품을 사용하지 마십시오.
  3. WHERE 절의 패턴 피하기
  4. 가장 낮은 카디널리티 식별자 (가능하면 1)에서 MATCH 패턴을 시작하고 바깥쪽으로 확장하십시오.
  5. 각 패턴에 대해 최소한의 확장을 수행하여 MATCH 패턴을 분리하십시오. 패턴 당 하나의 새로운 식별자를 추가하십시오.
  6. 전화 문의 : Wes!