이 문서에서는 Spanner Graph 쿼리 성능 조정을 위한 권장사항에 대해 설명합니다. 여기에는 다음과 같은 최적화가 포함됩니다.
- 노드와 에지에 대한 입력 테이블의 전체 스캔 방지
- 쿼리가 스토리지에서 읽어야 하는 데이터 양 감소
- 중간 데이터 크기 감소
낮은 카디널리티 노드에서 시작
낮은 카디널리티 노드에서 시작하도록 경로 순회를 작성합니다. 이 접근 방법은 중간 결과 집합을 작게 유지하고 쿼리 실행 속도를 높여줍니다.
예를 들어 다음 쿼리는 동일한 시맨틱스를 포함합니다.
정방향 에지 순회:
GRAPH FinGraph MATCH (p:Person {name:"Alex"})-[:Owns]->(a:Account {is_blocked: true}) RETURN p.id AS person_id, a.id AS account_id;역방향 에지 순회:
GRAPH FinGraph MATCH (a:Account {is_blocked:true})<-[:Owns]-(p:Person {name: "Alex"}) RETURN p.id AS person_id, a.id AS account_id;
이름이 Alex인 사람의 수가 차단된 계정의 수보다 적다고 가정하면 이 쿼리를 정방향 에지 순회로 작성하는 것이 좋습니다.
가변 길이 경로 순회의 경우 특히 낮은 카디널리티 노드로 시작하는 것이 중요합니다. 다음 예시는 지정된 계정으로부터 3번 이내에 이전된 계정을 찾는 권장 방법을 보여줍니다.
GRAPH FinGraph
MATCH (:Account {id: 7})-[:Transfers]->{1,3}(a:Account)
RETURN a.id;
기본적으로 모든 라벨 지정
Spanner Graph는 라벨이 생략된 경우 적격한 노드 및 에지 라벨을 추론합니다. 이러한 추론이 항상 가능하지 않을 수도 있고 필요한 것보다 많은 라벨을 스캔해야 할 수 있기 때문에 가능하면 모든 노드 및 에지에 대해 라벨을 지정하는 것이 좋습니다.
단일 MATCH 문
다음 예시에서는 지정된 계정으로부터 최대 3번의 이전으로 연결된 계정을 찾습니다.
GRAPH FinGraph
MATCH (src:Account {id: 7})-[:Transfers]->{1,3}(dst:Account)
RETURN dst.id;
MATCH 문 전체
동일한 요소를 참조하지만 서로 다른 MATCH 문에 지정되어 있으면 노드 및 에지에 라벨을 지정합니다.
다음 예시는 이에 대한 권장방법을 보여줍니다.
GRAPH FinGraph
MATCH (acct:Account {id: 7})-[:Transfers]->{1,3}(other_acct:Account)
RETURN acct, COUNT(DISTINCT other_acct) AS related_accts
GROUP BY acct
NEXT
MATCH (acct:Account)<-[:Owns]-(p:Person)
RETURN p.id AS person, acct.id AS acct, related_accts;
IS_FIRST를 사용하여 쿼리 최적화
IS_FIRST 함수를 사용하여 그래프에서 에지를 샘플링하고 순회를 제한하여 쿼리 성능을 향상시킬 수 있습니다. 이 함수는 카디널리티가 높은 노드를 처리하고 멀티 홉 쿼리를 최적화하는 데 도움이 됩니다.
지정한 샘플 크기가 너무 작으면 쿼리에서 데이터를 반환하지 않을 수 있습니다. 이로 인해 반환된 데이터와 향상된 쿼리 성능 간의 최적의 균형을 찾기 위해 다양한 샘플 크기를 시도해야 할 수 있습니다.
이러한 IS_FIRST 예시에서는 송금에 대한 Account 노드와 Transfers 에지가 있는 금융 그래프인 FinGraph를 사용합니다. FinGraph를 만들고 이를 사용하여 샘플 쿼리를 실행하려면 Spanner Graph 설정 및 쿼리를 참조하세요.
순회된 에지를 제한하여 쿼리 성능 향상
그래프를 쿼리할 때 일부 노드에는 다른 노드에 비해 들어오거나 나가는 에지 수가 훨씬 많을 수 있습니다. 이러한 카디널리티가 높은 노드를 슈퍼 노드 또는 허브 노드라고도 합니다. 슈퍼 노드를 통과하는 순회가 많은 양의 데이터 처리와 관련될 수 있으므로 슈퍼 노드로 인해 성능 문제가 발생할 수 있으며 이로 인해 데이터 왜도가 발생하고 실행 시간이 길어질 수 있습니다.
슈퍼 노드가 있는 그래프의 쿼리를 최적화하려면 FILTER 절 내에서 IS_FIRST 함수를 사용하여 쿼리가 노드에서 순회하는 에지 수를 제한합니다. FinGraph의 계정은 다른 계정보다 트랜잭션 수가 훨씬 많을 수 있으므로 IS_FIRST를 사용하여 비효율적인 쿼리를 방지할 수 있습니다. 이 기법은 슈퍼 노드에서 모든 연결을 완전하게 열거할 필요가 없는 경우에 특히 유용합니다.
다음 쿼리는 차단된 계정(a1)에서 직간접적으로 전송을 받는 계정(a2)을 찾습니다. 이 쿼리는 IS_FIRST를 사용하여 계정에 전송이 많은 경우 Account마다 고려할 Transfers 에지 수를 제한하여 성능 저하를 방지합니다.
GRAPH FinGraph
MATCH
(a1:Account {is_blocked: true})
-[e:Transfers WHERE e IN
{
MATCH -[selected_e:Transfers]->
FILTER IS_FIRST(@max_transfers_per_account) OVER (
PARTITION BY SOURCE_NODE_ID(selected_e)
ORDER BY selected_e.create_time DESC)
RETURN selected_e
}
]->{1,5}
(a2:Account)
RETURN a1.id AS src_id, a2.id AS dst_id;
이 예시에서는 다음을 사용합니다.
@max_transfers_per_account: 각 계정(a1)에 고려할Transfers에지 최대 수를 지정하는 쿼리 파라미터입니다.PARTITION BY SOURCE_NODE_ID(selected_e): 계정(a1)마다IS_FIRST제한이 독립적으로 적용되도록 합니다.ORDER BY selected_e.create_time DESC: 가장 최근의 전송이 반환되도록 지정합니다.
멀티홉 쿼리를 최적화하기 위해 중간 노드 샘플링
IS_FIRST를 사용하여 멀티 홉 쿼리에서 중간 노드를 샘플링해 쿼리 효율성을 향상시킬 수도 있습니다. 이 기법은 쿼리에서 각 중간 노드에 고려하는 경로 수를 제한하여 효율성을 향상시킵니다. 이렇게 하려면 멀티 홉 쿼리를 NEXT로 구분된 MATCH 문 여러 개로 나누고 샘플링해야 하는 중간 지점에 IS_FIRST를 적용합니다.
GRAPH FinGraph
MATCH (a1:Account {is_blocked: true})-[e1:Transfers]->(a2:Account)
FILTER IS_FIRST(1) OVER (PARTITION BY a2)
RETURN a1, a2
NEXT
MATCH (a2)-[e2:Transfers]->(a3:Account)
RETURN a1.id AS src_id, a2.id AS mid_id, a3.id AS dst_id;
IS_FIRST에서 이 쿼리를 최적화하는 방법을 이해하려면 다음 안내를 따르세요.
FILTER IS_FIRST(1) OVER (PARTITION BY a2)절은 첫 번째MATCH문에 적용됩니다.중간 계정 노드(
a2)마다IS_FIRST는 첫 번째 수신Transfers에지(e1)만 고려하므로 두 번째MATCH문에서 탐색할 경로 수가 줄어듭니다.특히
a2에 수신 전송이 많으면 두 번째MATCH에서 불필요한 데이터를 처리하지 않으므로 전체 2홉 쿼리의 효율성이 향상됩니다.