> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 딕셔너리 모범 사례

> 딕셔너리 레이아웃 선택, 딕셔너리와 JOIN 중 어떤 방식을 사용할지, 그리고 딕셔너리 사용량 모니터링에 대한 지침입니다.

이 페이지에서는 적절한 딕셔너리 레이아웃을 선택하는 실무 지침과, 딕셔너리가 JOIN보다 더 적합한 경우와 그렇지 않은 경우, 그리고 딕셔너리 사용량을 모니터링하는 방법을 다룹니다.

예시와 함께 딕셔너리를 소개하는 내용은 [메인 딕셔너리 가이드](/docs/ko/concepts/features/dictionaries/index)를 참조하십시오.

<div id="when-to-use-dictionaries-vs-joins">
  ## 딕셔너리와 JOIN 중 언제 사용해야 하나요
</div>

딕셔너리는 JOIN의 한쪽이 메모리에 들어가는 조회 테이블일 때 가장 효과적입니다. 일반적인 JOIN에서는 ClickHouse가 먼저 오른쪽에서 해시 테이블을 만든 뒤, 왼쪽 데이터를 사용해 이를 조회합니다. 이후 `WHERE` 필터로 대부분의 행이 걸러지더라도 마찬가지입니다. 최근 버전(24.12+)에서는 많은 경우 JOIN 전에 필터를 푸시하지만, 그렇다고 해서 오버헤드가 항상 없어지는 것은 아닙니다. 반면 딕셔너리를 사용하면 `dictGet`을 인라인으로 호출하므로, 조회는 이미 필터링을 통과한 행에 대해서만 수행됩니다.

하지만 `dictGet`이 항상 적절한 선택은 아닙니다. 테이블에서 많은 비율의 행에 대해 `dictGet`을 호출해야 한다면 — 예를 들어 `dictGet('dict', 'elevation', id) > 1800` 같은 `WHERE` 조건에서 — 네이티브 인덱스를 사용할 수 있는 일반 컬럼을 쓰는 편이 더 나을 수 있습니다. 일반 컬럼의 경우 ClickHouse가 `PREWHERE`를 사용해 그래뉼을 건너뛸 수 있지만, `dictGet`은 인덱스 지원 없이 행 단위로 평가됩니다.

경험칙으로는 다음과 같습니다:

* 조회 키를 이미 알고 있는 작은 차원 테이블에 대한 JOIN을 대체할 때는 딕셔너리를 사용합니다.
* 많은 행에서 조회된 값을 기준으로 필터링해야 할 때는 일반 컬럼과 인덱스를 사용합니다.

<div id="choosing-a-layout">
  ## 레이아웃 선택
</div>

`LAYOUT` 절은 딕셔너리의 내부 데이터 구조를 제어합니다. 사용 가능한 모든 레이아웃은 [레이아웃 참고](/docs/ko/reference/statements/create/dictionary/layouts/overview#storing-dictionaries-in-memory)에 문서화되어 있습니다.

레이아웃을 선택할 때는 다음 지침을 참고하십시오.

* **`flat`** — 가장 빠른 레이아웃입니다(단순 배열 오프셋 조회). 하지만 키는 `UInt64`여야 하며, 기본적으로 500,000개로 제한됩니다(`max_array_size`). 작거나 중간 규모의 테이블에서 단조 증가하는 정수 키에 가장 적합합니다. 희소 키 분포(예: 키 값이 1과 500,000인 경우)는 배열 크기가 가장 큰 키에 맞춰지므로 메모리를 낭비합니다. 500k 제한에 도달했다면 `hashed_array`로 전환할 시점이라는 의미입니다.
* **`hashed_array`** — 대부분의 사용 사례에서 권장되는 기본 레이아웃입니다. 속성은 배열에 저장하고, 키를 배열 인덱스에 매핑하는 해시 테이블을 사용합니다. `hashed`와 거의 비슷한 속도를 제공하면서도, 특히 속성이 많을 때 메모리 효율이 더 좋습니다.
* **`hashed`** — 전체 딕셔너리를 해시 테이블에 저장합니다. 속성이 매우 적을 때는 `hashed_array`보다 더 빠를 수 있지만, 속성 수가 늘어날수록 메모리 사용량이 더 커집니다.
* **`complex_key_hashed` / `complex_key_hashed_array`** — 키를 `UInt64`로 CAST할 수 없을 때(예: `String` 키) 사용합니다. 성능상의 절충점은 비복합 키 레이아웃과 동일합니다.
* **`sparse_hashed`** — `hashed`보다 메모리 사용량을 줄이는 대신 CPU를 더 사용합니다. 최선의 선택인 경우는 드물며, 단일 속성만 있을 때에만 효율적입니다. 대부분의 경우 `hashed_array`가 더 적합합니다.
* **`cache` / `ssd_cache`** — 자주 액세스되는 키만 캐시합니다. 전체 데이터셋이 메모리에 들어가지 않을 때 유용하지만, 캐시 미스가 발생하면 조회가 원본 소스에 도달할 수 있습니다. 지연 시간에 민감한 workload에는 권장되지 않습니다.
* **`direct`** — 메모리에 저장하지 않고 매 조회마다 원본 소스를 쿼리합니다. 데이터가 너무 자주 변경되어 캐시하기 어렵거나, 딕셔너리가 메모리에 담기에는 너무 클 때 사용하십시오.

<div id="monitoring-dictionary-usage">
  ## 딕셔너리 사용 모니터링
</div>

[`system.dictionaries`](/docs/ko/reference/system-tables/dictionaries) 테이블을 통해 메모리 사용량과 상태를 확인할 수 있습니다:

```sql theme={null}
SELECT
    name,
    status,
    element_count,
    formatReadableSize(bytes_allocated) AS size,
    query_count,
    hit_rate,
    found_rate,
    last_exception
FROM system.dictionaries
```

키 컬럼:

* `bytes_allocated` — 딕셔너리가 사용하는 메모리입니다. 딕셔너리는 데이터를 압축하지 않은 상태로 저장하므로, 압축된 테이블 크기보다 훨씬 클 수 있습니다.
* `hit_rate` 및 `found_rate` — `cache` 레이아웃의 효과를 평가하는 데 유용합니다.
* `last_exception` — 딕셔너리를 로드하지 못하거나 갱신에 실패할 때 이를 확인하십시오.
