字典 DICTIONARY 是什么
字典把外部数据(ClickHouse 表、MySQL、文件、HTTP 等)加载成内存键值结构,用 dictGet 做维度补全与枚举翻译,避免每行去 join。定义语法是 CREATE DICTIONARY ... PRIMARY KEY ... SOURCE(...) LIFETIME(MIN 300 MAX 600) LAYOUT(HASHED())。取值用 dictGet('db.dict', 'attr', key) 或 dictGetOrDefault,运行状态可以在 system.dictionaries 里查看。
基本信息
| 定义 | CREATE DICTIONARY … PRIMARY KEY … SOURCE(…) LIFETIME(…) LAYOUT(…) |
|---|---|
| 数据源 | 本地表、MySQL、文件、HTTP 等 |
| 取值 | dictGet / dictGetOrDefault |
| 状态查看 | system.dictionaries 的 status、element_count、bytes_allocated、last_exception |
| 刷新 | LIFETIME 自动刷新,或 SYSTEM RELOAD DICTIONARY 手动刷新 |
| 所属系统 | ClickHouse |
典型使用场景
- 枚举翻译:把状态码、地区码换成可读名称
- 维度补全:给事实表补上类目、渠道等属性
- 替代小表 join:字典常驻内存,点查比临时 join 更快
- 外部数据接入:直接读 MySQL 维表,减少同步链路
- 手动刷新:维表刚变更完需要立刻生效时用 RELOAD
定义与取值
定义与取值
CREATE DICTIONARY analytics.users_dict
(
id UInt64,
name String,
level UInt8
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(TABLE 'users' DB 'analytics'))
LIFETIME(MIN 300 MAX 600) -- 300 到 600 秒之间自动刷新
LAYOUT(HASHED());
SELECT dictGet('analytics.users_dict', 'name', toUInt64(1001)); -- 按键取属性定义要素读法
| 项 | 含义 | 注意 |
|---|---|---|
| PRIMARY KEY | 字典的键 | 要与源表的键对应 |
| SOURCE | 数据来源 | 本地表、MySQL、文件、HTTP 等 |
| LIFETIME | 自动刷新区间 | 在 MIN 与 MAX 之间随机取值 |
| LAYOUT | 内存组织方式 | HASHED 适合小字典 |
| system.dictionaries | 运行状态 | last_exception 记录加载失败原因 |
LIFETIME 控制自动刷新的区间,也可以用 SYSTEM RELOAD DICTIONARY 手动刷新,源表刚变更完需要立刻生效时用手动方式。
HASHED 布局适合键数量不大的字典,百万级以上要先看内存占用再决定布局,否则容易把节点内存吃掉。
字典加载失败时 dictGet 会返回空值或默认值,出现大面积空值的第一个排查点就是 system.dictionaries 的 last_exception。
查询时传入的键类型要与字典定义一致,键是整数却传字符串会取到默认值,必要时用 toUInt64 一类函数显式转换。
用字典替代 join 的前提是维表规模可控;维表很大或变更频繁时,常规 join 反而更灵活,别为了省一次 join 把内存吃满。
需要多级翻译(编码到名称再到分组)时,按层级定义多个字典比堆在一条 SQL 里做多次取值更清晰,也便于单独刷新。
字典是各节点本地加载的,集群里每台机器都会占一份内存;改字典定义后要在集群范围内执行,否则各节点加载的内容可能不一致。