Microsoft Fabric 그래프에 대한 GQL 쿼리 성능 최적화

이 문서에서는 Microsoft Fabric 그래프로 작업할 때 예측 및 효율적으로 수행하는 GQL(그래프 쿼리 언어) 쿼리를 작성하기 위한 지침을 제공합니다. 권장 사항은 현재 플랫폼 동작 및 문서화된 제약 조건을 기반으로 합니다.

그래프 크기, 결과 크기 및 쿼리 시간 제한에 대한 하드 제한은 현재 제한을 참조하세요. 이 문서의 몇 가지 권장 사항은 그래프 스키마를 디자인하는 방법과도 관련이 있습니다. 자세한 내용은 그래프 스키마 디자인을 참조하세요.

의미론에 따라 필터를 배치하세요

어떤 노드나 간선이 매치에 참여할 수 있는지 정의한 술어를 그래프 패턴 안에 넣습니다. 완성된 매칭을 포스트필터하기 위해 문장 수준 MATCH ... WHERE 조건을 사용하거나, 술어가 이전 문장에서 생성된 행에 적용될 때는 별도의 FILTER 문장을 사용하세요.

예를 들어, 매칭된 노드에 대한 조건에 대해 패턴 수준 WHERE 절을 사용하세요:

MATCH (p:Person WHERE p.birthday < 19940101)-[:workAt]->(c:Company WHERE c.id > 1000)
RETURN p.firstName, p.lastName, c.name

별도의 FILTER 조건은 기본 ALL 경로 탐색을 사용하는 일반 의무 매치 후에 동일한 조건을 표현할 수 있습니다:

MATCH (p:Person)-[:workAt]->(c:Company)
FILTER p.birthday < 19940101 AND c.id > 1000
RETURN p.firstName, p.lastName, c.name

쿼리 옵티마이저는 그렇게 해도 쿼리 의미가 유지되는 경우 스캔 중에 동등한 술어를 적용할 수 있으므로, 인라인 구문이 본질적으로 더 빠른 것은 아닙니다. 조건이 적용될 때를 나타내는 형태를 선택하세요.

술어 배치에 따라 ANY SHORTEST의 결과가 달라질 수 있습니다. 인라인 프레디킷은 최단 경로 선택 대상이 되는 경로를 제한합니다. 경로 선택 후에는 문장 수준 WHERE 또는 그 이후 FILTER 의 명령이 적용되어, 긴 경로를 선택하지 않고 선택한 최단 경로를 제거할 수 있습니다. 현재 MATCH ... WHERE 의 한계와 신뢰할 수 있는 배치 패턴에 대해서는 경로 선택 전후 술어를 배치하는 방법을 참조하세요.

OPTIONAL MATCH의 위치도 중요합니다. 인라인 FILTER은 선택적 일치를 제한하지만, 그 뒤의 WHERE는 NULL로 확장된 행을 제거할 수 있습니다.

팁 (조언)

패턴 수준을 WHERE SQL JOIN ... ON 조건과 유사하다고 생각합니다. 이 방법은 결과된 행을 필터링하는 대신 어떤 매칭이 자격을 갖추는지 설명합니다.

필요한 속성만 반환합니다.

시나리오에 필요한 노드 및 에지 속성만 반환합니다. 전체 노드를 반환하거나 속성의 하위 집합만 필요한 경우에는 RETURN *을 사용하지 마십시오.

불필요한 속성을 선택하면 데이터 읽기, serialization 비용 및 응답 크기가 증가합니다. 그래프 모델링 중에는 노드 유형 속성으로 필요한 소스 열만 선택하세요.

권장: 좁은 프로젝션.

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, p.lastName, c.name

피하기 위해: 전체 노드를 반환합니다.

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN *

비고

쿼리 또는 분석에 필요한 경우 그래프 모델링 중에 노드 형식 속성만 추가합니다. 노드당 속성이 적어도 storage 및 쿼리 오버헤드가 모두 줄어듭니다.

결과 집합 크기 제한

카디널리티가 높을 수 있는 노드 또는 관계를 쿼리할 때 LIMIT 또는 다른 경계 조건을 적용하세요. 바인딩되지 않은 그래프 일치는 플랫폼 제한에 접근하는 매우 큰 결과 집합을 생성할 수 있습니다.

권장: 제한된 결과입니다.

MATCH (p:Person)-[:knows]->(friend:Person)
RETURN p.firstName, friend.firstName
LIMIT 1000

피할 것: 제한 없는 높은 카디널리티 일치.

MATCH (p:Person)-[:knows]->(friend:Person)
RETURN p.firstName, friend.firstName

중요합니다

그래프는 내부 이진 표현이 64MB를 초과하는 쿼리 응답을 절단합니다. 단축된 응답은 공공 코드 01000 와 정통 GQLSTATUS 01M11를 포함한 추가 상태를 포함합니다. 필터를 사용하고, 프로젝션 범위를 좁히고, LIMIT 결과의 크기를 줄이세요. 자세한 내용은 현재 제한 사항을 참조하세요.

탐색을 간단하고 집중적으로 유지하세요.

깊이 중첩되거나 매우 복잡한 그래프 패턴을 사용하지 않습니다. 특정 질문에 직접 대답하는 간단한 대상 순회를 사용합니다. 가변 길이 패턴의 각 추가 홉은 특히 조밀하게 연결된 그래프에서 엔진이 평가하는 경로 수를 기하급수적으로 늘릴 수 있습니다.

권장: 엄격한 제한.

-- Use the narrowest hop range that answers your question
MATCH (p:Person)-[:knows]->{1,3}(friend:Person)
RETURN p.firstName, friend.firstName
LIMIT 1000

피하세요: 명확한 필요 없이 넓은 이동 범위.

-- A wider range on a dense graph is more expensive
MATCH (p:Person)-[:knows]->{1,8}(friend:Person)
RETURN *

중요합니다

시각적 쿼리 빌더는 가변 길이 경로를 8홉으로 제한하지만, 이 사용자 인터페이스 제한은 코드 편집기의 GQL에는 적용되지 않습니다. 시나리오가 허용하는 가장 엄격한 범위를 사용하세요. 더 넓은 범위가 더 많은 경로를 연결할 수 있기 때문입니다.

경로가 엣지를 반복하지 않을 때는 TRAIL을 사용하세요

유효한 경로에서 동일한 간선을 반복하면 안 되는 경우에는 TRAIL 경로 모드를 사용하세요. 사이클이 있는 그래프에서는 이 제한이 기본 WALK 모드에 비해 매칭 경로 수를 줄일 수도 있습니다.

-- TRAIL prevents revisiting the same :knows edge
MATCH TRAIL (src:Person)-[:knows]->{1,4}(dst:Person)
WHERE src.firstName = 'Alice' AND dst.firstName = 'Bob'
RETURN count(*) AS numPaths

TRAIL이 없으면 순환 그래프에 대해 동일한 쿼리를 실행할 때 같은 간선을 반복하는 경로가 반환될 수 있습니다. 일반적인 성능 최적화로 취급하기보다는 필요한 경로 의미론에 맞는 모드를 사용하세요 TRAIL .

무한한 ALL WALK 패턴은 사이클이 무한히 많은 경로를 생성할 수 있기 때문에 지원되지 않습니다. 무한한 TRAIL, SIMPLE, 패턴 ACYCLIC 이 종료되더라도 여전히 많은 경로를 열거할 수 있다. 쿼리가 무한한 탐색을 요구하지 않는 한 유한 상한을 사용하세요.

효율적인 조인을 위해 공유 변수 사용

쿼리에 여러 관계의 데이터가 필요한 경우 공유 변수를 사용하여 동일한 엔터티의 패턴을 조인합니다. 공유 변수가 없으면 패턴은 두 패턴의 모든 일치 항목 조합인 카티전 제품을 생성하여 훨씬 더 큰 결과 집합을 생성할 수 있습니다.

권장: 공유 변수 p 는 패턴을 조인합니다.

-- Single shared variable ensures an efficient join
MATCH (p:Person)-[:workAt]->(c:Company),
      (p)-[:isLocatedIn]->(city:City)
RETURN p.firstName, c.name AS company, city.name AS city
LIMIT 1000

피하기: 공유 변수가 없는 독립 패턴.

-- Without a shared variable, this produces a cartesian product
MATCH (p1:Person)-[:workAt]->(c:Company),
      (p2:Person)-[:isLocatedIn]->(city:City)
RETURN p1.firstName, c.name, p2.firstName, city.name

카티지아 제품은 한 패턴의 모든 결과와 다른 패턴의 모든 결과를 쌍으로 만듭니다. 1,000개의 행과 일치하고 500개의 행과 Person-workAt->Company 일치하는 경우 Person-isLocatedIn->City 쿼리는 1,000개 × 500 = 500,000개의 행을 반환합니다. 공유 변수를 추가하면 조인이 제한되므로 일치하는 쌍만 반환됩니다.

노드를 식별할 때 주요 속성에 대해 필터링하세요

노드 키 제약을 정의하여 노드를 고유하게 식별하고 데이터 무결성을 강제합니다. 특정 노드가 필요할 때는 패턴 술어에 그 노드의 키 속성을 포함시켜 관련 없는 노드와 매칭하지 않도록 하세요.

예를 들어, 그래프 유형이 id를 Person 노드의 키로 정의하는 경우:

CONSTRAINT person_pk
  FOR (n:Person) REQUIRE n.id IS KEY

그 후 언제 그 사람이 필요한지 필터링하세요 id :

MATCH (p:Person WHERE p.id = 12345)-[:workAt]->(c:Company)
RETURN p.firstName, c.name

필터가 없으면 쿼리는 Person 간선을 순회하기 전에 모든 workAt 노드와 일치합니다:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, c.name

팁 (조언)

핵심 제약 조건은 정체성과 고유성을 확립합니다. 그것만으로는 특정 물리적 검색이나 쿼리 계획을 보장하지 않습니다.

적절한 데이터 형식 선택

각 속성의 값과 의도된 연산을 나타내는 데이터 타입을 선택하세요. 예를 들어, 숫자를 문자열로 저장하는 대신 숫자 타입을 사용해 수치로 계산하거나 비교하는 방식을 사용하세요.

지원되는 데이터 형식은 현재 제한 사항(데이터 형식 및 지원되는 속성 형식)을 참조하세요.

가능한 경우 동일한 가장자리를 독립적으로 트래버스하는 별도의 쿼리를 실행하는 대신 단일 그래프 패턴으로 관련 엔터티를 검색합니다. 순회를 결합하면 중복 패턴 일치가 방지되고 N+1 쿼리 문제가 방지됩니다. 여기서 하나의 초기 쿼리는 각 결과 행에 대해 별도의 쿼리를 트리거합니다.

권장: 단일 결합 패턴입니다.

MATCH (c:Customer)-[:purchases]->(o:`Order`)-[:`contains`]->(product:`Product`)
RETURN c.fullName, o, product.productName
LIMIT 1000

피하기: 동일한 가장자리를 트래버스하는 두 개의 별도 쿼리.

-- Query 1: fetch 100 orders
MATCH (c:Customer)-[:purchases]->(o:`Order`)
RETURN c.fullName, o
LIMIT 100

-- Query 2: repeat for each returned order, substituting its key value
MATCH (o:`Order` WHERE o.SalesOrderDetailID_K = 12345)-[:`contains`]->(product:`Product`)
RETURN o, product.productName

실제 데이터 볼륨에 대한 쿼리 테스트

작은 데이터 세트에 대해 잘 수행되는 쿼리는 선형적으로 확장되지 않을 수 있습니다. 예상 프로덕션 워크로드를 나타내는 데이터 볼륨으로 쿼리를 테스트합니다.

  • 필터 및 제한을 포함하는 보수적인 쿼리 셰이프를 선호합니다.
  • 큰 그래프에 대해 예비 "모든 항목 반환" 쿼리를 사용하지 않습니다.
  • 20분 제한 시간을 기준으로 쿼리 기간을 모니터링합니다.