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

# cache 字典布局

> 将字典存储在固定大小的内存缓存中。

`cached` 字典布局类型会将字典存储在一个具有固定单元数的缓存中。
这些单元保存的是经常使用的元素。

字典键的类型为 [UInt64](/zh/reference/data-types/int-uint)。

查找字典时，会先查缓存。对于每个数据块，凡是在缓存中未命中或已过期的键，都会通过 `SELECT attrs... FROM db.table WHERE id IN (k1, k2, ...)` 从源中请求。接收到的数据随后会写入缓存。

如果在字典中找不到键，则会创建缓存更新任务并将其加入更新队列。更新队列的属性可通过 `max_update_queue_size`、`update_queue_push_timeout_milliseconds`、`query_wait_timeout_milliseconds`、`max_threads_for_updates` 这些设置来控制。

对于 cache 字典，可以设置缓存中数据的过期 [lifetime](/zh/reference/statements/create/dictionary/lifetime)。如果某个单元中的数据自加载以来经过的时间超过了 `lifetime`，则该单元的值将不再使用，该键也会变为过期状态。下次需要使用该键时，会重新发起请求。此行为可通过 `allow_read_expired_keys` 设置进行配置。

这是所有字典存储方式中效率最低的一种。缓存的速度在很大程度上取决于设置是否正确以及具体的使用场景。cache 类型字典只有在命中率足够高时才能获得良好性能 (建议达到 99% 或更高) 。你可以在 [system.dictionaries](/zh/reference/system-tables/dictionaries) 表中查看平均命中率。

如果将 `allow_read_expired_keys` 设置为 1 (默认为 0) ，则字典支持异步更新。如果客户端请求的键都在缓存中，但其中部分已过期，则字典会先向客户端返回这些过期键，同时异步从源中重新请求它们。

要提升缓存性能，请使用带 `LIMIT` 的子查询，并从字典外部调用该函数。

支持所有类型的源。

设置示例：

<Tabs>
  <Tab title="DDL">
    ```sql theme={null}
    LAYOUT(CACHE(SIZE_IN_CELLS 1000000000))
    ```
  </Tab>

  <Tab title="配置文件">
    ```xml theme={null}
    <layout>
        <cache>
            <!-- 缓存大小，以单元数计。向上取整为 2 的幂。 -->
            <size_in_cells>1000000000</size_in_cells>
            <!-- 允许读取过期键。 -->
            <allow_read_expired_keys>0</allow_read_expired_keys>
            <!-- 更新队列的最大大小。 -->
            <max_update_queue_size>100000</max_update_queue_size>
            <!-- 将更新任务推入队列的最大超时时间（毫秒）。 -->
            <update_queue_push_timeout_milliseconds>10</update_queue_push_timeout_milliseconds>
            <!-- 等待更新任务完成的最大超时时间（毫秒）。 -->
            <query_wait_timeout_milliseconds>60000</query_wait_timeout_milliseconds>
            <!-- cache 字典更新的最大线程数。 -->
            <max_threads_for_updates>4</max_threads_for_updates>
        </cache>
    </layout>
    ```
  </Tab>
</Tabs>

<br />

请将缓存大小设置得足够大。你需要通过试验来确定单元数：

1. 先设置一个值。
2. 运行查询，直到缓存被完全填满。
3. 使用 `system.dictionaries` 表评估内存消耗。
4. 增加或减少单元数，直到达到所需的内存消耗。

<Note>
  不建议将 ClickHouse 用作此布局的源。字典查找需要随机点读，而这并不是 ClickHouse 优化的访问模式。
</Note>
