> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ClickHouse에서 lazy materialization이 무엇인지 설명하는 문서

# Lazy materialization

이 문서에서는 lazy materialization의 작동 방식과 이것이 ClickHouse의 전반적인 I/O 최적화 스택에 어떻게 포함되는지 설명합니다.
또한 lazy materialization이 쿼리 성능을 어떻게 향상시키는지 보여 주는 실제 예시를 소개합니다.

<Tip>
  **버전 25.4부터 사용 가능**

  lazy materialization은 ClickHouse 버전 25.4에서 도입되었으며 기본적으로 활성화되어 있습니다.
</Tip>

<div id="overview">
  ## 개요
</div>

수년에 걸쳐 ClickHouse는 I/O를 과감하게 줄이기 위해 여러 계층의 최적화 기법을 도입해 왔습니다.
이러한 기법은 ClickHouse의 속도와 효율성을 뒷받침하는 기반입니다:

| 최적화                                                                                   | 설명                                                                                                                                                                          |                                                           |                                                                                                                                                                  |
| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**컬럼 지향 스토리지**](/ko/get-started/about/intro#row-oriented-vs-column-oriented-storage) | 쿼리에 필요하지 않은 컬럼 전체를 건너뛸 수 있으며, 유사한 값을 함께 묶어 높은 압축률도 달성할 수 있으므로 데이터 로딩 중 I/O를 최소화합니다.                                                                                         |                                                           |                                                                                                                                                                  |
| [**희소 프라이머리 인덱스**](/ko/guides/clickhouse/data-modelling/sparse-primary-indexes)       | [**보조 데이터 스키핑 인덱스**](/ko/concepts/features/performance/skip-indexes/skipping-indexes)                                                                                       | [**프로젝션**](/ko/concepts/features/projections/projections) | \_인덱싱된 컬럼\_의 필터와 일치할 가능성이 있는 [그래뉼](/ko/concepts/core-concepts/glossary#granule) (행 블록)을 식별해 관련 없는 데이터를 프루닝합니다. 이러한 기법은 그래뉼 수준에서 동작하며, 각각 단독으로 또는 조합해 사용할 수 있습니다. |
| [**PREWHERE**](/ko/reference/statements/select/prewhere)                              | *인덱싱되지 않은* 컬럼의 필터에 대해서도 일치 여부를 확인해, 그렇지 않으면 로드된 후 버려질 데이터를 미리 건너뜁니다. 이는 독립적으로 동작할 수도 있고, 인덱스가 선택한 그래뉼을 더 정교하게 좁히는 데 사용될 수도 있으며, *모든* 컬럼 필터와 일치하지 않는 행을 건너뛰어 그래뉼 프루닝을 보완합니다. |                                                           |                                                                                                                                                                  |
| [**쿼리 조건 캐시**](/ko/concepts/features/performance/caches/query-condition-cache)        | 이전 실행에서 어떤 그래뉼이 모든 필터와 일치했는지를 기억해 반복 쿼리를 더 빠르게 처리합니다. 따라서 쿼리 구조가 바뀌더라도 ClickHouse는 일치하지 않았던 그래뉼을 읽고 필터링하는 작업을 건너뛸 수 있습니다.                                                   |                                                           |                                                                                                                                                                  |

앞서 언급한 I/O 최적화는 읽어야 하는 데이터를 크게 줄일 수 있지만, 여전히 `WHERE` 절을 통과한 행의 모든 컬럼을 정렬, 집계, `LIMIT` 같은 작업을 수행하기 전에 로드해야 한다고 가정합니다. 하지만 일부 컬럼은 나중에야 필요하거나, 어떤 데이터는 `WHERE` 절을 통과하더라도 결국 전혀 필요하지 않다면 어떨까요?
이때 lazy materialization이 필요합니다. 이는 I/O 최적화 스택을 완성하는 별개의 개선 기법입니다:

* 인덱싱은 `PREWHERE`와 함께 `WHERE` 절의 컬럼 필터와 일치하는 행만 처리되도록 보장합니다.
* Lazy materialization은 이를 바탕으로, 쿼리 실행 계획에서 실제로 필요해질 때까지 컬럼 읽기를 미룹니다.
  필터링 이후에도 다음 작업(예: 정렬)에 필요한 컬럼만 즉시 로드됩니다.
  나머지 컬럼은 뒤로 미뤄지며, `LIMIT` 때문에 최종 결과를 만드는 데 필요한 만큼만, 즉 대개 일부만 읽으면 됩니다.
  따라서 lazy materialization은 Top N 쿼리에서 특히 강력합니다. 최종 결과를 만들기 위해 특정 컬럼들(대개 크기가 큰 컬럼들)에서 소수의 행만 필요할 수 있기 때문입니다.

<div id="worked-example">
  ## 예시로 살펴보기
</div>

lazy materialization을 자세히 알아보려면 ["ClickHouse gets lazier (and faster): Introducing lazy materialization"](https://clickhouse.com/blog/clickhouse-gets-lazier-and-faster-introducing-lazy-materialization#speed-without-filters-lazy-materialization-in-isolation) 블로그 게시물을 참고하시기를 강력히 권장합니다. 아래 예시는 앞서 언급한 블로그 게시물에서 가져온 내용을 여기에서 다시 소개한 것으로, lazy materialization을 통해 ClickHouse 쿼리 실행 시간이 219초에서 단 139밀리초로 단축될 수 있음을 보여줍니다(1576배 향상).

인덱싱과 `PREWHERE`의 이점을 활용하려면 쿼리에 필터가 있어야 합니다. 인덱싱에는 프라이머리 키(primary key) 컬럼에 대한 필터가 필요하고, `PREWHERE`에는 임의의 컬럼에 대한 필터가 필요합니다.
그 위에 lazy materialization을 자연스럽게 적용할 수 있지만, 앞서 언급한 다른 최적화와는 달리 컬럼 필터가 전혀 없는 쿼리도 가속할 수 있습니다.

다음 예시 쿼리는 날짜, 제품, 평점, 검증 상태와 관계없이 도움이 되었다는 투표 수가 가장 많은 Amazon 리뷰를 찾고, 제목, 헤드라인, 전체 텍스트와 함께 상위 3개를 반환합니다.

먼저 lazy materialization을 비활성화한 상태에서([`query_plan_optimize_lazy_materialization`](/ko/reference/settings/session-settings#query_plan_optimize_lazy_materialization) 사용), 쿼리를 콜드 파일 시스템 캐시 상태로 실행합니다:

```sql title="Query" theme={null}
SELECT
    helpful_votes,
    product_title,
    review_headline,
    review_body
FROM amazon.amazon_reviews
ORDER BY helpful_votes DESC
LIMIT 3
FORMAT Vertical
SETTINGS
    query_plan_optimize_lazy_materialization = false;
```

```response title="Response" highlight={22-23} theme={null}
Row 1:
──────
helpful_votes:   47524
product_title:   Kindle: Amazon's Original Wireless Reading Device (1st generation)
review_headline: Why and how the Kindle changes everything
review_body:     This is less a \"pros and cons\" review than a hopefully use...

Row 2:
──────
helpful_votes:   41393
product_title:   BIC Cristal For Her Ball Pen, 1.0mm, Black, 16ct (MSLP16-Blk)
review_headline: FINALLY!
review_body:     Someone has answered my gentle prayers and FINALLY designed ...

Row 3:
──────
helpful_votes:   41278
product_title:   The Mountain Kids 100% Cotton Three Wolf Moon T-Shirt
review_headline: Dual Function Design
review_body:     This item has wolves on it which makes it intrinsically swee...

0 rows in set. Elapsed: 219.071 sec. Processed 150.96 million rows, 71.38 GB (689.08 thousand rows/s., 325.81 MB/s.)
Peak memory usage: 1.11 GiB.
```

다음으로 쿼리를 다시 실행합니다(이번에도 콜드 파일 시스템 캐시로 실행). 이번에는 lazy materialization을 활성화한 상태입니다:

```sql title="Query" highlight={11} theme={null}
SELECT
    helpful_votes,
    product_title,
    review_headline,
    review_body
FROM amazon.amazon_reviews
ORDER BY helpful_votes DESC
LIMIT 3
FORMAT Vertical
SETTINGS
query_plan_optimize_lazy_materialization = true;
```

<Tip>
  일반적으로는 `query_plan_optimize_lazy_materialization = true`를 명시적으로 설정하지 않아도 lazy materialization의 이점을 얻을 수 있습니다.
  기본적으로 활성화되어 있습니다.
</Tip>

```response title="Response" highlight={22-23} theme={null}
Row 1:
──────
helpful_votes:   47524
product_title:   Kindle: Amazon's Original Wireless Reading Device (1st generation)
review_headline: Why and how the Kindle changes everything
review_body:     This is less a \"pros and cons\" review than a hopefully use...

Row 2:
──────
helpful_votes:   41393
product_title:   BIC Cristal For Her Ball Pen, 1.0mm, Black, 16ct (MSLP16-Blk)
review_headline: FINALLY!
review_body:     Someone has answered my gentle prayers and FINALLY designed ...

Row 3:
──────
helpful_votes:   41278
product_title:   The Mountain Kids 100% Cotton Three Wolf Moon T-Shirt
review_headline: Dual Function Design
review_body:     This item has wolves on it which makes it intrinsically swee...

0 rows in set. Elapsed: 0.139 sec. Processed 150.96 million rows, 1.81 GB (1.09 billion rows/s., 13.06 GB/s.)
Peak memory usage: 3.80 MiB.
```

lazy materialization을 끈 경우와 켠 경우의 성능 차이를 살펴보겠습니다:

| 메트릭        | lazy materialization 비활성화 | lazy materialization 활성화 | 개선 효과        |
| ---------- | ------------------------- | ------------------------ | ------------ |
| 경과 시간      | 219.071 sec               | 0.139 sec                | 약 1576배 더 빠름 |
| 읽은 데이터 양   | 71.38 GB                  | 1.81 GB                  | 약 40배 감소     |
| 최대 메모리 사용량 | 1.11 GiB                  | 3.80 MiB                 | 약 300배 감소    |

<div id="confirm-lazy-materialization">
  ## 쿼리 실행 계획에서 lazy materialization을 확인하는 방법
</div>

[`EXPLAIN`](/ko/reference/statements/explain) 절을 사용해 쿼리의 논리 실행 계획을 살펴보면, 앞선 쿼리에서 lazy materialization이 사용되었는지 확인할 수 있습니다:

```sql theme={null}
EXPLAIN actions = 1
SELECT
    helpful_votes,
    product_title,
    review_headline,
    review_body
FROM amazon.amazon_reviews
ORDER BY helpful_votes DESC
LIMIT 3
SETTINGS
    query_plan_optimize_lazy_materialization = true;
```

```response highlight={2} theme={null}
...
Lazily read columns: review_headline, review_body, product_title
  Limit
    Sorting
      ReadFromMergeTree
```

연산자 계획은 아래에서 위로 읽을 수 있으며, ClickHouse가 정렬과 제한을 적용한 후에야 3개의 큰 String 컬럼을 읽는다는 점을 확인할 수 있습니다.
