range_hashed
字典以哈希表的形式存储在内存中,其中包含按顺序排列的范围数组及其对应的值。
这种存储方式与 hashed 的工作方式相同,并且除了键之外,还支持使用日期/时间范围 (任意数值类型) 。
示例:该表包含每个广告商的折扣,格式如下:
┌─advertiser_id─┬─discount_start_date─┬─discount_end_date─┬─amount─┐
│ 123 │ 2015-01-16 │ 2015-01-31 │ 0.25 │
│ 123 │ 2015-01-01 │ 2015-01-15 │ 0.15 │
│ 456 │ 2015-01-01 │ 2015-01-15 │ 0.05 │
└───────────────┴─────────────────────┴───────────────────┴────────┘要为日期范围使用样本,请在 structure 中定义 range_min 和 range_max 元素。这些元素必须包含 name 和 type 元素 (如果未指定 type,则使用默认类型 Date) 。type 可以是任意数值类型 (Date / DateTime / UInt64 / Int32 / 其他) 。
示例:
CREATE DICTIONARY discounts_dict (
advertiser_id UInt64,
discount_start_date Date,
discount_end_date Date,
amount Float64
)
PRIMARY KEY id
SOURCE(CLICKHOUSE(TABLE 'discounts'))
LIFETIME(MIN 1 MAX 1000)
LAYOUT(RANGE_HASHED(range_lookup_strategy 'max'))
RANGE(MIN discount_start_date MAX discount_end_date)<layout>
<range_hashed>
<!-- 重叠范围的策略(min/max)。默认值:min(返回匹配范围中 min(range_min -> range_max) 值最小的范围) -->
<range_lookup_strategy>min</range_lookup_strategy>
</range_hashed>
</layout>
<structure>
<id>
<name>advertiser_id</name>
</id>
<range_min>
<name>discount_start_date</name>
<type>Date</type>
</range_min>
<range_max>
<name>discount_end_date</name>
<type>Date</type>
</range_max>
...要使用这些字典,你需要向 dictGet 函数额外传递一个参数,用于指定要选择的范围:
dictGet('dict_name', 'attr_name', id, date)查询示例:
SELECT dictGet('discounts_dict', 'amount', 1, '2022-10-20'::Date);此函数返回指定 id 的值,以及包含传入日期的日期范围。
算法细节:
- 如果未找到
id,或未找到该id对应的范围,则返回该 attribute 类型的默认值。 - 如果存在重叠范围且
range_lookup_strategy=min,则返回range_min最小的匹配范围;如果找到多个范围,则返回range_max最小的范围;如果仍然找到多个范围 (多个范围具有相同的range_min和range_max) ,则从中随机返回一个范围。 - 如果存在重叠范围且
range_lookup_strategy=max,则返回range_min最大的匹配范围;如果找到多个范围,则返回range_max最大的范围;如果仍然找到多个范围 (多个范围具有相同的range_min和range_max) ,则从中随机返回一个范围。 - 如果
range_max为NULL,则该范围为开放区间。NULL被视为可能的最大值。对于range_min,可使用1970-01-01或0(-MAX_INT) 作为开放值。
配置示例:
CREATE DICTIONARY somedict(
Abcdef UInt64,
StartTimeStamp UInt64,
EndTimeStamp UInt64,
XXXType String DEFAULT ''
)
PRIMARY KEY Abcdef
RANGE(MIN StartTimeStamp MAX EndTimeStamp)<clickhouse>
<dictionary>
...
<layout>
<range_hashed />
</layout>
<structure>
<id>
<name>Abcdef</name>
</id>
<range_min>
<name>StartTimeStamp</name>
<type>UInt64</type>
</range_min>
<range_max>
<name>EndTimeStamp</name>
<type>UInt64</type>
</range_max>
<attribute>
<name>XXXType</name>
<type>String</type>
<null_value />
</attribute>
</structure>
</dictionary>
</clickhouse>包含重叠范围和开放区间的配置示例:
CREATE TABLE discounts
(
advertiser_id UInt64,
discount_start_date Date,
discount_end_date Nullable(Date),
amount Float64
)
ENGINE = Memory;
INSERT INTO discounts VALUES (1, '2015-01-01', Null, 0.1);
INSERT INTO discounts VALUES (1, '2015-01-15', Null, 0.2);
INSERT INTO discounts VALUES (2, '2015-01-01', '2015-01-15', 0.3);
INSERT INTO discounts VALUES (2, '2015-01-04', '2015-01-10', 0.4);
INSERT INTO discounts VALUES (3, '1970-01-01', '2015-01-15', 0.5);
INSERT INTO discounts VALUES (3, '1970-01-01', '2015-01-10', 0.6);
SELECT * FROM discounts ORDER BY advertiser_id, discount_start_date;
┌complex_key_range_hashed
字典以哈希表的形式存储在内存中,其中包含按顺序排列的范围数组及其对应的值 (参见 range_hashed) 。这种存储类型适用于复合keys。
配置示例:
CREATE DICTIONARY range_dictionary
(
CountryID UInt64,
CountryKey String,
StartDate Date,
EndDate Date,
Tax Float64 DEFAULT 0.2
)
PRIMARY KEY CountryID, CountryKey
SOURCE(CLICKHOUSE(TABLE 'date_table'))
LIFETIME(MIN 1 MAX 1000)
LAYOUT(COMPLEX_KEY_RANGE_HASHED())
RANGE(MIN StartDate MAX EndDate);