ip_trie 字典专为按网络前缀进行 IP 地址查找而设计。
它以 CIDR 表示法存储 IP 范围,并可快速判断给定 IP 属于哪个前缀(例如子网或 ASN 范围),非常适合用于基于 IP 的检索,如地理位置定位或网络分类。
示例
假设我们在 ClickHouse 中有一张表,包含 IP 前缀及其映射关系:
CREATE TABLE my_ip_addresses (
prefix String,
asn UInt32,
cca2 String
)
ENGINE = MergeTree
PRIMARY KEY prefix;
INSERT INTO my_ip_addresses VALUES
('202.79.32.0/20', 17501, 'NP'),
('2620:0:870::/48', 3856, 'US'),
('2a02:6b8:1::/48', 13238, 'RU'),
('2001:db8::/32', 65536, 'ZZ')
;
让我们为此表定义一个 ip_trie 字典。ip_trie 布局需要一个复合键:
CREATE DICTIONARY my_ip_trie_dictionary (
prefix String,
asn UInt32,
cca2 String DEFAULT '??'
)
PRIMARY KEY prefix
SOURCE(CLICKHOUSE(TABLE 'my_ip_addresses'))
LAYOUT(IP_TRIE)
LIFETIME(3600);
<structure>
<key>
<attribute>
<name>prefix</name>
<type>String</type>
</attribute>
</key>
<attribute>
<name>asn</name>
<type>UInt32</type>
<null_value />
</attribute>
<attribute>
<name>cca2</name>
<type>String</type>
<null_value>??</null_value>
</attribute>
...
</structure>
<layout>
<ip_trie>
<!-- 键属性 `prefix` 可以通过 dictGetString 获取。 -->
<!-- 此选项会增加内存占用。 -->
<access_to_key_from_attributes>true</access_to_key_from_attributes>
</ip_trie>
</layout>
键必须只有一个 String 类型的属性,并且该属性的值为允许的 IP 前缀。其他类型目前尚不支持。
语法如下所示:
dictGetT('dict_name', 'attr_name', ip)
该函数的参数可以是用于 IPv4 的 UInt32,或用于 IPv6 的 FixedString(16)。例如:
SELECT dictGet('my_ip_trie_dictionary', 'cca2', toIPv4('202.79.32.10')) AS result;
┌─result─┐
│ NP │
└────────┘
SELECT dictGet('my_ip_trie_dictionary', 'asn', IPv6StringToNum('2001:db8::1')) AS result;
┌─result─┐
│ 65536 │
└────────┘
SELECT dictGet('my_ip_trie_dictionary', ('asn', 'cca2'), IPv6StringToNum('2001:db8::1')) AS result;
┌─result───────┐
│ (65536,'ZZ') │
└──────────────┘
目前尚不支持其他类型。该 FUNCTION 返回与此 IP 地址匹配的前缀所对应的属性。如果存在重叠前缀,则返回最具体的前缀。
数据必须完全驻留在 RAM 中。