1、MergeTree
1.1データTTL
1.1.1列レベルのTTL
-- 创建一张包含列级别TTL的表
create table test.ttl_table_v1 ( \
id String, \ -- 主键字段不能被声明TTL表达式
create_time DateTime, \ -- 需要依托对某个DateTime或Date类型字段的INTERVAL操作,来表达TTL的过期时间
code String TTL create_time + INTERVAL 10 SECOND, \ -- 当系统时间超过该TTL超时时间则字段会被清理并且设置为字段类型的默认值
type UInt8 TTL create_time + INTERVAL 10 SECOND \
)ENGINE = MergeTree() \
PARTITION BY toYYYYMM(create_time) \
ORDER BY id;
insert into table test.ttl_table_v1 values('A000', now(), 'C1', 1), \
('A000', now()+ INTERVAL 10 MINUTE, 'C1', 1);
select * from test.ttl_table_v1;
-- 执行强制触发TTL清理
optimize table test.ttl_table_v1 final;
-- 修改表的TTL字段或者新增TTL字段
alter table test.ttl_table_v1 modify column code string TTL create_time + INTERVAL 1 DAY
1.1.2テーブルレベルのTTL
create table test.ttl_table_v2 ( \
id String, \
create_time DateTime, \
code String TTL create_time + INTERVAL 10 SECOND, \
type UInt8 \
)ENGINE = MergeTree() \
PARTITION BY toYYYYMM(create_time) \
ORDER BY create_time \
-- 这里定义表级别的TTL,当出发TTL清除的时候,满足过期时间的数据行将会被删除
TTL create_time + INTERVAL 1 DAY;
-- 新增或者修改表级别的TTL
alter table test.ttl_table_v1 modify TTL create_time + INTERVAL 3 DAY
1.1.3TTL操作メカニズム
テーブルレベルのTTLが設定されている場合、データを書き込むときは、データパーティションがユニットとして使用され、各パーティションのディレクトリにttl.txtファイルが生成されます。
[root@localhost test]# tree ttl_table_v2/
ttl_table_v2/
├── 202103_1_1_0
│ ├── checksums.txt
│ ├── columns.txt
│ ├── count.txt
│ ├── data.bin
│ ├── data.mrk3
│ ├── default_compression_codec.txt
│ ├── minmax_create_time.idx
│ ├── partition.dat
│ ├── primary.idx
│ └── ttl.txt
├── detached
└── format_version.txt
ttl format version: 1
{"columns":[{"name":"code","min":0,"max":0},{"name":"type","min":0,"max":0}],"table":{"min":1615175460,"max":1615176099}}
"columns":[{"name":"code","min":0,"max":0}]是列级别ttl的描述信息。
"table":{"min":1615175460,"max":1615176099}是表界别的tt描述信息。
min,max分别保存了当前数据分区中,ttl指定日期字段的最小值、最大值分别于INTERVAL表达式计算后的时间戳。
処理ロジック:
1. MergeTreeは、パーティションディレクトリを1つの単位として使用して、ttl.txtファイルを介して有効期限を記録し、それを後続の判断の基礎として使用します。
2.データのバッチが書き込まれるたびに、INTERVAL式の計算結果に基づいてパーティション全体のttl.txtファイルが生成されます。
3. TTL期限切れデータを削除するロジックは、MergeTreeがパーティションをマージするときにのみトリガーされます。
4.パーティションの削除を選択する場合、欲張りアルゴリズムが使用されます。そのアルゴリズムルールは、最も早く期限切れになるパーティションをできるだけ多く見つけ、その年齢で最も古い同僚を見つけることです(マージの数が最も多い) 、MaxBlockNumの方が大きい)。
チップ:
1.マージ頻度を待機するデフォルトのTTLは、MergeTreeのmerge_with_ttl_timeoutパラメーターによって制御され、デフォルトは1日です。この値の設定が小さすぎると、パフォーマンスの問題が発生します。
2.自動開始とマージに加えて、手動でマージすることもできます
-- 触发一个分区合并 optimize table table_name -- 触发所有的分区合并 optimize table table_name final
3.現在、TTL宣言を削除する方法はありませんが、グローバルTTLのマージタスクの開始と停止を制御する方法を提供します(テーブルルックアップレベルに応じてではありません)。
system stop/start ttl merges
1.2マルチパスストレージ戦略
デフォルトの戦略:すべてのパーティションデータは、config.xmlで構成されたパスに自動的に保存されます。
JBOD戦略:複数のディスクがサーバーにマウントされているが、RAIDが使用されていないシナリオに適しています。JBOD(単なるディスクの束)はポーリング戦略です。INSERTまたはMERGEを実行するたびに、生成された新しいパーティションがポーリングして各ディスクに書き込みます。単一のディスクに障害が発生した場合、そのディスクは破棄されます。JBODを使用して書き込みます。戦略入力されたデータのこの部分。
HOT / COLD戦略:サーバーがさまざまなタイプのディスク(SSD / HDD)に接続されているシナリオに適しています。ステージングHOTとCOLDの2つの領域が保存されます。SSDはHOTエリアで使用され、HDDはCOLDエリアで使用されます。MerGeTreeにデータが書き込まれると、最初にHOT領域にパーティションディレクトリが作成され、データが保存されます。パーティションデータのサイズがしきい値に達すると、データは自動的にCOLD領域に移動します。各エリアでは、複数のディスクもサポートされているため、JBOD戦略を単一のエリアの書き込みプロセスに適用することもできます。
config.xmlのstorage_configurationラベルは、ストレージポリシーを構成するためのstorage_configurationラベルであり、ディスクとポリシーの下に2つのラベルがあります。
<storage_configuration>
<disks>
<!--自定义磁盘名字-->
<disk_name_a>
<!--定义磁盘的路径-->
<path>/clickhouse/data</path>
<!--定义磁盘的预留空间-->
<keep_free_space_bytes>4096</keep_free_space_bytes>
</disk_name_a>
</disks>
<policies>
<!--自定义策略名字-->
<policy_name_a>
<volumes>
<!--卷的自定义名称-->
<volume_name_a>
<!--关联的配置内的磁盘-->
<disk>disk_name_a</disk>
<disk>disk_name_b</disk>
<!--表示在这个卷的单个disk磁盘中,一个数据分区的最大存储阈值,如果当前分区的数据大小超过阈值,
则之后的分区会写入下一个disk磁盘-->
<max_data_part_size_part>4096</max_data_part_size_part>
</volume_name_a>
</volumes>
<!--如果当前卷的可用空间小于factor因子,并且定义了多个卷,则数据会自定向下一个卷移动-->
<move_factor>2.0</move_factor>
</policy_name_a>
</policies>
</storage_configuration>
1.2.1JBOD戦略
<storage_configuration>
<disks>
<!--自定义磁盘名字-->
<disk_hot>
<!--定义磁盘的路径-->
<path>/clickhouse/data</path>
<!--定义磁盘的预留空间-->
<keep_free_space_bytes>4096</keep_free_space_bytes>
</disk_hot>
<disk_cold>
<!--定义磁盘的路径-->
<path>/clickhouse/data</path>
<!--定义磁盘的预留空间-->
<keep_free_space_bytes>4096</keep_free_space_bytes>
</disk_cold>
</disks>
<policies>
<!--自定义策略名字-->
<default_jbod>
<volumes>
<!--卷的自定义名称-->
<jbod>
<!--关联的配置内的磁盘-->
<disk>disk_hot</disk>
<disk>disk_cold</disk>
</jbod>
</volumes>
</default_jbod>
</policies>
</storage_configuration>
JBODストレージ戦略は上記で構成されています。使用する前に、2つのストレージディレクトリの所有者をクリックハウスユーザーに変更することを忘れないでください。クリックハウスサーバーサービスを再起動する必要があります。
SQLを実行して、構成されたディスクを表示します。
select \
name, \
path, \
formatReadableSize(free_space) as free, \
formatReadableSize(total_space) as total_space, \
formatReadableSize(keep_free_space) as keep_free_space \
from \
system.disks;
次のSQLを実行して、構成済みのストレージポリシーを表示します。
select * from system.storage_policies;
構成された戦略を使用します。
-- 创建表
create table test.jbod_table(
id UInt64
)engine = MergeTree()
Order By id
-- 配置表的存储策略
Setting storage_policy = 'default_jbod'
-- 写入数据
insert into table jbod_table select rand() from numbers(10);
-- 查看分区系统表, 分区存储在哪个磁盘上
select name, disk_name from system.parts where table = 'test.jbod_table';
概要:複数のディスクがディスクグループ、つまりボリュームボリュームを形成します。新しいデータパーティションが生成されるたびに、パーティションディレクトリがポーリングされ、ボリュームとディスクで定義された順序で各ディスクに書き込まれます。
1.2.2HOT / COLD戦略
<storage_configuration>
<disks>
<!--自定义磁盘名字-->
<disk_hot>
<!--定义磁盘的路径-->
<path>/clickhouse/data</path>
<!--定义磁盘的预留空间-->
<keep_free_space_bytes>4096</keep_free_space_bytes>
</disk_hot>
<disk_cold>
<!--定义磁盘的路径-->
<path>/clickhouse/data</path>
<!--定义磁盘的预留空间-->
<keep_free_space_bytes>4096</keep_free_space_bytes>
</disk_cold>
</disks>
<policies>
<!--自定义策略名字-->
<moving_from_hot_to_cold>
<volumes>
<!--卷的自定义名称-->
<hot>
<!--关联的配置内的磁盘-->
<disk>disk_hot</disk>
<!--表示在这个磁盘下如果一个分区数据大小超过1M,则需要被移动到紧邻的下一个磁盘卷-->
<max_data_part_size>1073741824</max_data_part_size>
</hot>
<cold>
<disk>disk_cold</disk>
</cold>
</volumes>
<!--如果当前卷的可用空间小于factor因子,并且定义了多个卷,则数据会自定向下一个卷移动-->
<move_factor>2.0</move_factor>
</moving_from_hot_to_cold>
</policies>
</storage_configuration>
構成された戦略を使用します。
-- 创建表
create table test.hot_cold_table(
id UInt64
)engine = MergeTree()
Order By id
-- 配置表的存储策略
Setting storage_policy = 'moving_from_hot_to_cold'
-- 写入数据
insert into table hot_cold_table select rand() from numbers(10);
-- 查看分区系统表, 分区存储在哪个磁盘上
select name, disk_name from system.parts where table = 'test.hot_cold_table';
チップ:
1.一度に1MBが書き込まれると、パーティションはCOLDボリュームにも書き込まれます。
2.複数のディスクボリュームがディスクグループボリュームグループを形成します。新しいデータパーティションが生成されるたびに、しきい値サイズ(max_data_part_size)に従って、パーティションディレクトリがポーリングされ、ディスクボリュームで定義された順序で各ボリュームに書き込まれます。ボリュームグループ。ディスクの下。
3.現在、MergeTreeのストレージリストは変更できませんが、パーティションディレクトリは移動できます。
-- 将某个分区移动到当前存储策略中当前卷下的其他的disk磁盘: alter table hot_cold_table move part "all_1_2_1" to disk "disk_hot1" -- 将某个分区移动到当前存储策略中其他的volume卷 alter table hot_cold_table move part "all_1_2_1" to volume "cold"
2、ReplacingMergeTree
ReplacingMergeTreeは重複排除用に設計されており、パーティションがマージされるときに重複データを削除できます。
を使用する場合は、ENGINE = ReplacingMergeTree(ver)を設定するだけで済みます。ここで、verはオプションのパラメーターであり、バージョン番号としてUInt *、Date、またはDateTimeタイプフィールドを指定します。このパラメーターは、データ重複排除に使用されるアルゴリズムを決定します。
-- 创建表
create table test.replace_table ( \
id String, \
create_time DateTime, \
code String \
)ENGINE = ReplacingMergeTree() \
PARTITION BY toYYYYMM(create_time) \
ORDER BY (id, code) \
primary key id;
-- 执行以下的命令2次及以上
insert into table test.replace_table values('A111', '2020-03-05 15:00:00', 'C1'),('A111', '2020-04-05 15:00:00', 'C1'),('A111', '2020-05-05 15:00:00', 'C1');
-- 然后手动清理表
optimize table test.replace_table final;
-- 然后查看表数据, 最后主键还是有重复的
select * from test.replace_table
ヒント1:ReplacingMergeTreeは、パーティション単位で重複データを削除します。同じデータパーティション内の重複データのみを削除でき、異なるデータパーティション間で重複データを削除することはできません。
-- 创建表,这里加上版本号字段
create table test.replace_table ( \
id String, \
create_time DateTime, \
code String \
)ENGINE = ReplacingMergeTree(create_time) \
PARTITION BY toYYYYMM(create_time) \
ORDER BY id \
primary key id;
optimize table test.replace_table final;
ヒント2:バージョン番号フィールドが追加されている場合、重複データを削除すると、同じデータセットのバージョン番号列フィールドの最大行が保持されます。
総括する:
(1)データ重複を判断するための唯一のキーとしてソートキーによる順序を使用します
(2)重複データを削除するロジックは、パーティションがマージされたときにのみトリガーされます
(3)データパーティション単位で重複データを削除します。パーティションがマージされると、パーティション内の重複データが削除されることに同意します。異なるパーティション間のデータは削除できません。
(4)データ重複排除を行う場合、パーティション内のデータはorder byでソートされているため、隣接する重複データを見つけることができます。
(5)データ重複排除の2つの戦略:
- verバージョン番号が設定されていない場合、同じ繰り返しデータセットの最後の行が保持されます。
- verバージョン番号が設定されている場合、同じ繰り返しデータのセットでverフィールドの値が最大の行が保持されます。
3、SummingMergeTree
SummingMergeTreeの集計は、ORDERBYで定義されたソートキーに基づいています。通常、主キーを定義するためにソートキーを定義するだけで済みますが、ソートキーとプライマリキーの両方を定義する場合、プライマリキーの列フィールドはソートキーのプレフィックスである必要があります。
ソートキーを変更する必要がある場合は、次のコマンドを渡します。
alter table table_name modify order by (A, B)
注:並べ替えキーを変更する場合、元の基準でのみフィールドを減らすことができます。新しい並べ替えフィールドを追加する場合は、alteradd列を介してのみ新しいフィールドを追加できます。
SummingMergeTreeの使用方法:
ENGINE = SummingMergeTree((col1、col2、…))
Col1、col2はcolumnsパラメーターの値です。これは、SUMによって要約された列フィールドを指定するための主キー以外の他の数値フィールドを設定するために使用されるオプションのパラメーターです。このパラメーターが入力されていない場合、主キーを除くすべての数値タイプが合計されます。
create table summing_table ( \
id String, \
city String, \
v1 UInt32, \
v2 Float64, \
create_time Datetime \
)ENGINE = SummingMergeTree() \
PARTITION BY toYYYYMM(create_time) \
ORDER BY (id, city) \
PRIMARY KEY id;
ネストされたデータ型を使用する場合:
create table summing_table_nested ( \
id String, \
-- 在使用嵌套数据类型的时候,默认情况下,会以嵌套类型中的第一个字段作为聚合条件Key
-- 如果要使用嵌套中的复合字段作为聚合Key, 则除第一个字段外,任何名称是以Key, Id或Type为后缀结尾的字段,都将和第一个字段一起组成复合Key
nestMap Nested( \
id UInt32, \
Key UInt32, \
val UInt64 \
), \
create_time Datetime \
)ENGINE = SummingMergeTree() \
PARTITION BY toYYYYMM(create_time) \
ORDER BY id;
まとめ:
- 集計データの条件キーとしてOrderBYソートキーを使用します
- サマリーロジックは、パーティションがマージされたときにのみトリガーされます
- データをデータパーティションの単位で集計します。パーティションがマージされると、同じデータパーティション内の同じ集約キーを持つデータがマージおよび要約されますが、異なるパーティション内のデータは要約されません。
- エンジンの定義時に列(非主キー数値型フィールド)が指定されている場合、SUMはこれらの列フィールドを集約します。指定されていない場合、すべての非主キー数値型フィールドを集約します。
- データ集約中に、同じパーティション内の同じ集約キーを持つデータの複数の行が1つの行にマージされます。その中で、要約フィールドはSUM計算になります。これらの非要約フィールドには、データの最初の行の値が使用されます。
- ネストされたタイプの構造をサポートしますが、列フィールドはマップサフィックスで終わる必要があります。ネストされたタイプでは、最初のフィールドがデフォルトで集計キーとして使用されます。最初のフィールドを除いて、名前がKey、Id、またはTypeのサフィックスで終わるフィールドは、最初のフィールドとの複合キーを形成します。
4、AggregatingMergeTree
使用する場合:ENGINE = AggregatingMergeTree();
パーティションがマージされると、各データパーティションはORDERBYに従って集約されます。AggregatingFunctionデータ型を定義することにより、使用される集計関数の種類とそれらの列フィールドの計算が実現されます。
create table agg_table ( \
id String, \
city String, \
-- uniq 去重操作
code AggregateFunction(uniq, String), \
-- sum 求和
value AggregateFunction(sum, UInt32), \
create_time datetime \
) engine = AggregatingMergeTree() \
partition by toYYYYMM(create_time) \
order by (id, city) \
primary key id;
AggregateFunctionは、クリックハウスによって提供される特別なデータ型であり、中間状態の結果をバイナリ形式で格納できます。
AggregateFunctionの列フィールドの場合、書き込み時に* State関数を呼び出す必要があります。データをクエリするときは、対応する* Merge関数を呼び出す必要があります。ここで、*は定義で使用される集計関数を表します。
書き込むときは、uniqとsumに対応するuniqState関数とsumState関数を呼び出し、INSERTSELECTを使用する必要があります。
insert into table agg_table
select 'A000', 'wuhan', uniqState('code01'), sumState(toUInt32(100)), '2021-03-06 00:08:00'
クエリを実行するときは、uniqMerge、sumMerge関数を呼び出す必要があります。
select id, city, uniqMerge(code), sumMerge(value) from agg_table group by id, city;
AggregatingMergeTreeは、マテリアライズドビューと組み合わせて使用されます。
- (1)まず、MergeTreeを下のテーブルとして使用し、詳細データの全量を格納し、外部にリアルタイムのクエリを提供するデータリストがあります。
create table agg_table_basic ( \
id String, \
city String, \
code String, \
value UInt32 \
)ENGINE = MergeTree() \
partition by city \
order by (id, city);
- (2)下のテーブルに基づいてマテリアライズド・ビューを作成します。データが書き込まれると、下のテーブルに書き込まれます。データはマテリアライズド・ビューに自動的に同期され、AggragatingMergeTreeエンジンのルールに従って処理されます。クエリを実行すると、マテリアライズドビューAggragatingMergeTreeがクエリされます。
create materialized view agg_view \
engine = AggregatingMergeTree() \
partition by city \
order by (id, city) \
as select \
id, \
city, \
uniqState(code) as code, \
sumState(value) as value \
from agg_table_basic \
group by id, city;
insert into table agg_table_basic values('A000', 'wuhan', 'code1', 100), \
('A000', 'wuhan', 'code2', 200), \
('A000', 'sichuan', 'code1', 150), \
('A000', 'beijing', 'code3', 1000);
select id, city, sumMerge(value), uniqMerge(code) from agg_view group by id, city;
総括する:
- データ集約の条件キーとしてソートキーによる順序を使用します
- AggregationFunctionフィールドタイプを使用して、集計関数のタイプと集計フィールドを定義します。
- 集計計算ロジックは、パーティションがマージされたときにのみトリガーされます。
- データはデータパーティションの単位で集約されます。パーティションがマージされると、同じデータパーティション内の同じ集約キーを持つデータがマージおよび計算されますが、異なるパーティションのデータは計算されません。
- データ計算を行う場合、パーティション内のデータはソート順でソートされているため、同じ集計キーで隣接するデータを見つけることができます。
- データを集約する場合、同じパーティション内の同じ集約キーを持つデータの複数の行が1つの行にマージされます。非主キーおよび非AggragateFunctionタイプのフィールドの場合、データの最初の行の値が使用されます。
- AggragateFunctionタイプフィールドはバイナリストレージを使用します。AggregateFunctionの列フィールドの場合、書き込み時に* State関数を呼び出す必要があります。データをクエリするときは、対応する* Merge関数を呼び出す必要があります。ここで、*は定義で使用される集計関数を表します。
- AggragatingMergeTreeは通常、マテリアライズドビューのエンジンとして使用され、通常のMergeTreeと組み合わせて使用されます。
5、CollapsingMergeTree
CollapsingMergeTree(折りたたみマージツリー)は、追加、生成、削除のアイデアを通じて行レベルのデータの変更と削除をサポートするテーブルエンジンです。
符号をフィールドとして定義することにより、データ行のステータスが記録されます。符号が1の場合、これは有効なデータ行であることを意味します。符号が-1の場合、このデータ行を削除する必要があることを意味します。CollapsingMergeTreeパーティションがマージされると、符号が1と-1の同じデータパーティション内のデータがオフセットされて削除されます。
使用方法:ENGINE = CollapsingMergeTree(sign)
create table collapse_table
(
id String,
code UInt32,
create_time DateTime,
-- sign 是一个Int8类型的标志位字段
sign Int8
)ENGINE = CollapsingMergeTree(sign )
partition by toYYYYMM(create_time)
order by id;