cached 字典布局类型会将字典存储在一个具有固定单元数的缓存中。
这些单元保存的是经常使用的元素。
字典键的类型为 UInt64。
查找字典时,会先查缓存。对于每个数据块,凡是在缓存中未命中或已过期的键,都会通过 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。如果某个单元中的数据自加载以来经过的时间超过了 lifetime,则该单元的值将不再使用,该键也会变为过期状态。下次需要使用该键时,会重新发起请求。此行为可通过 allow_read_expired_keys 设置进行配置。
这是所有字典存储方式中效率最低的一种。缓存的速度在很大程度上取决于设置是否正确以及具体的使用场景。cache 类型字典只有在命中率足够高时才能获得良好性能 (建议达到 99% 或更高) 。你可以在 system.dictionaries 表中查看平均命中率。
如果将 allow_read_expired_keys 设置为 1 (默认为 0) ,则字典支持异步更新。如果客户端请求的键都在缓存中,但其中部分已过期,则字典会先向客户端返回这些过期键,同时异步从源中重新请求它们。
要提升缓存性能,请使用带 LIMIT 的子查询,并从字典外部调用该函数。
支持所有类型的源。
设置示例:
- DDL
- 配置文件
请将缓存大小设置得足够大。你需要通过试验来确定单元数:
- 先设置一个值。
- 运行查询,直到缓存被完全填满。
- 使用
system.dictionaries表评估内存消耗。 - 增加或减少单元数,直到达到所需的内存消耗。
不建议将 ClickHouse 用作此布局的源。字典查找需要随机点读,而这并不是 ClickHouse 优化的访问模式。