이번에 더 배울 것
Cypher는 원하는 결과만 적는 선언형 언어라, 어떤 순서로 찾을지는 플래너가 정합니다. 쿼리 앞에 EXPLAIN을 붙이면 실행하지 않고 계획과 추정 행 수만 보여 줍니다. PROFILE을 붙이면 실제로 실행하면서 연산자마다 실제 행 수와 db hits를 잽니다. db hits는 노드·속성·인덱스 항목을 읽는 것과 같은 저장소 수준 작업의 횟수입니다.
계획은 아래쪽 잎에서 위쪽 ProduceResults로 읽습니다. 자주 보는 연산자는 모든 노드를 읽는 AllNodesScan, 한 레이블의 노드를 모두 읽는 NodeByLabelScan, 인덱스로 바로 찾는 NodeIndexSeek, 관계를 따라가는 Expand(All), 조건으로 거르는 Filter입니다. 앵커 조건에 인덱스가 있어야 할 자리에서 Scan이 보이면 의심해 볼 지점입니다.
읽는 요령은 세 가지입니다. 앞 단계에서 많은 행을 만들고 Filter에서 대부분 버린다면 거르는 조건을 앞당기거나 인덱스를 둘 방법을 찾습니다. 추정 행과 실제 행이 크게 다르면 통계가 낡았을 수 있습니다. db hits는 같은 데이터에서 쿼리 변형끼리 비교할 때 의미가 있습니다. PROFILE은 실제로 실행되므로 쓰기 쿼리에 붙이면 데이터가 실제로 바뀐다는 점도 기억합니다.
작은 예제로 따라가기
PROFILE MATCH (p:Person {email:'minsu@lab.kr'})-[:AUTHORED]->(x:Paper) RETURN x.title에서 email 인덱스가 없으면 NodeByLabelScan이 :Person 100,000행을 만들고 Filter가 1행만 남깁니다(가상 수치).
email에 인덱스나 유일성 제약을 만든 뒤에는 첫 연산자가 NodeIndexSeek 계열로 바뀌어 1행에서 출발합니다.
이어지는 Expand(All)는 민수의 AUTHORED 관계 2개를 따라가 2행을 만듭니다. 두 계획의 결과는 같고 일한 양만 다릅니다.
첫 연산자 맞히기
:Person 노드 100,000개와 다른 레이블 노드 50,000개가 있는 가상 데이터에서, 각 조건의 첫 연산자와 그 연산자가 내보내는 행 수를 먼저 예상하세요.
레이블이 없으면 어떤 노드든 후보라 모든 노드를 읽어야 합니다.
학습을 시작하면 새 문제를 직접 풀고 확인 퀴즈를 마친 뒤 선택한 본과정 회차로 돌아갑니다.