개요
앞서 언급한 I/O 최적화는 읽어야 하는 데이터를 크게 줄일 수 있지만, 여전히
WHERE 절을 통과한 행의 모든 컬럼을 정렬, 집계, LIMIT 같은 작업을 수행하기 전에 로드해야 한다고 가정합니다. 하지만 일부 컬럼은 나중에야 필요하거나, 어떤 데이터는 WHERE 절을 통과하더라도 결국 전혀 필요하지 않다면 어떨까요?
이때 lazy materialization이 필요합니다. 이는 I/O 최적화 스택을 완성하는 별개의 개선 기법입니다:
- 인덱싱은
PREWHERE와 함께WHERE절의 컬럼 필터와 일치하는 행만 처리되도록 보장합니다. - Lazy materialization은 이를 바탕으로, 쿼리 실행 계획에서 실제로 필요해질 때까지 컬럼 읽기를 미룹니다.
필터링 이후에도 다음 작업(예: 정렬)에 필요한 컬럼만 즉시 로드됩니다.
나머지 컬럼은 뒤로 미뤄지며,
LIMIT때문에 최종 결과를 만드는 데 필요한 만큼만, 즉 대개 일부만 읽으면 됩니다. 따라서 lazy materialization은 Top N 쿼리에서 특히 강력합니다. 최종 결과를 만들기 위해 특정 컬럼들(대개 크기가 큰 컬럼들)에서 소수의 행만 필요할 수 있기 때문입니다.
예시로 살펴보기
PREWHERE의 이점을 활용하려면 쿼리에 필터가 있어야 합니다. 인덱싱에는 프라이머리 키(primary key) 컬럼에 대한 필터가 필요하고, PREWHERE에는 임의의 컬럼에 대한 필터가 필요합니다.
그 위에 lazy materialization을 자연스럽게 적용할 수 있지만, 앞서 언급한 다른 최적화와는 달리 컬럼 필터가 전혀 없는 쿼리도 가속할 수 있습니다.
다음 예시 쿼리는 날짜, 제품, 평점, 검증 상태와 관계없이 도움이 되었다는 투표 수가 가장 많은 Amazon 리뷰를 찾고, 제목, 헤드라인, 전체 텍스트와 함께 상위 3개를 반환합니다.
먼저 lazy materialization을 비활성화한 상태에서(query_plan_optimize_lazy_materialization 사용), 쿼리를 콜드 파일 시스템 캐시 상태로 실행합니다:
Query
Response
Query
Response
쿼리 실행 계획에서 lazy materialization을 확인하는 방법
EXPLAIN 절을 사용해 쿼리의 논리 실행 계획을 살펴보면, 앞선 쿼리에서 lazy materialization이 사용되었는지 확인할 수 있습니다: