range_hashed
Dictionary は、順序付けられた範囲の Array とそれに対応する値を持つハッシュテーブルの形式で、メモリ内に格納されます。
この格納方式は 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>
...これらの Dictionary を使用するには、範囲の選択対象となる追加の引数を dictGet 関数に渡す必要があります:
dictGet('dict_name', 'attr_name', id, date)クエリ例:
SELECT dictGet('discounts_dict', 'amount', 1, '2022-10-20'::Date);この関数は、指定した id に対応する値と、指定された日付を含む日付範囲を返します。
アルゴリズムの詳細:
idが見つからない場合、またはそのidに対応する範囲が見つからない場合は、その属性の型のデフォルト値を返します。- 重複する範囲があり、
range_lookup_strategy=minの場合は、一致した範囲のうちrange_minが最小のものを返します。該当する範囲が複数ある場合は、range_maxが最小の範囲を返します。それでも複数ある場合 (複数の範囲でrange_minとrange_maxが同じ場合) は、その中からランダムに 1 つの範囲を返します。 - 重複する範囲があり、
range_lookup_strategy=maxの場合は、一致した範囲のうちrange_minが最大のものを返します。該当する範囲が複数ある場合は、range_maxが最大の範囲を返します。それでも複数ある場合 (複数の範囲でrange_minとrange_maxが同じ場合) は、その中からランダムに 1 つの範囲を返します。 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
Dictionary は、順序付けされた範囲の Array と、それに対応する値を持つハッシュテーブルの形式でメモリ内に格納されます (range_hashed を参照) 。このストレージ方式は、複合キーで使用するためのものです。
設定例:
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);