进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容!
🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客
📌订阅:拥抱独家专题,你的订阅将点燃我的创作热情!
👍点赞:赞同优秀创作,你的点赞是对我创作最大的认可!
⭐️ 收藏:收藏原创博文,让我们一起打造IT界的荣耀与辉煌!
✏️评论:留下心声墨迹,你的评论将是我努力改进的方向!
目录
1. MergeTree
2. MergeTree建表语句
3. 示例一
4. 示例二
在所有的表引擎中,最为核心的当属MergeTree系列表引擎,这些表引擎拥有最为强大的性能和最广泛的使用场合。对于非MergeTree系列的其他引擎而言,主要用于特殊用途,场景相对有限。而MergeTree系列表引擎是官方主推的存储引擎,有主键索引、数据分区、数据副本、数据采样、删除和修改等功能,支持几乎所有ClickHouse核心功能。
MergeTree系列表引擎包含:MergeTree、ReplacingMergeTree、SummingMergeTree(汇总求和功能)、AggregatingMergeTree(聚合功能)、CollapsingMergeTree(折叠删除功能)、VersionedCollapsingMergeTree(版本折叠功能)引擎,在这些的基础上还可以叠加Replicated和Distributed。
1. MergeTree
MergeTree在写入一批数据时,数据总会以数据片段的形式写入磁盘,且数据片段在磁盘上不可修改。为了避免片段过多,ClickHouse会通过后台线程,定期合并这些数据片段,属于相同分区的数据片段会被合成一个新的片段。这种数据片段往复合并的特点,也正是合并树名称的由来。
MergeTree作为家族系列最基础的表引擎,主要有以下特点:
- 存储的数据按照主键排序:创建稀疏索引加快数据查询速度。
- 支持数据分区,可以通过PARTITION BY语句指定分区字段。
- 支持数据副本。
- 支持数据采样。
2. MergeTree建表语句
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster](name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],...INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2) ENGINE = MergeTree()ORDER BY expr[PARTITION BY expr][PRIMARY KEY expr][SAMPLE BY expr][TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...][SETTINGS name=value, ...]
- 关于以上建表语句的解释如下:
- ENGINE:ENGINE = MergeTree(),MergeTree引擎没有参数。
- ORDER BY:排序字段。比如ORDER BY (Col1, Col2),值得注意的是,如果没有使用 PRIMARY KEY 显式的指定主键ORDER BY排序字段自动作为主键。如果不需要排序,则可以使用 ORDER BY tuple() 语法,这样的话,创建的表也就不包含主键。这种情况下,ClickHouse会按照插入的顺序存储数据。必选项。
- PARTITION BY:分区字段,例如要按月分区,可以使用表达式 toYYYYMM(date_column),这里的date_column是一个Date类型的列,分区名的格式会是"YYYYMM"。可选。
- PRIMARY KEY:指定主键,如果排序字段与主键不一致,可以单独指定主键字段。否则默认主键是排序字段。大部分情况下不需要再专门指定一个 PRIMARY KEY 子句,注意,在MergeTree中主键并不用于去重,而是用于索引,加快查询速度。可选。
另外,如果指定了PRIMARY KEY与排序字段不一致,要保证PRIMARY KEY 指定的主键是ORDER BY 指定字段的前缀,比如:
--允许... ...ORDER BY (A,B,C)PRIMARY KEY A--报错... ...ORDER BY (A,B,C)PRIMARY KEY BDB::Exception: Primary key must be a prefix of the sorting key
这种强制约束保障了即便在两者定义不同的情况下,主键仍然是排序键的前缀,不会出现索引与数据顺序混乱的问题。
- SAMPLE BY:采样字段,如果指定了该字段,那么主键中也必须包含该字段。比如 SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))。可选。
- TTL:数据的存活时间。在MergeTree中,可以为某个列字段或整张表设置TTL。当时间到达时,如果是列字段级别的TTL,则会删除这一列的数据;如果是表级别的TTL,则会删除整张表的数据。可选。
- SETTINGS:额外的参数配置。可选。
3. 示例一
#在库 newdb中创建表 t_mt ,使用MergeTree引擎node1 :) create table t_mt(:-] id UInt8,:-] name String,:-] age UInt8,:-] birthday Date,:-] location String:-] ) engine = MergeTree():-] order by (id,age):-] partition by toYYYYMM(birthday);#向表中插入数据node1 :) insert into t_mt values (1,'张三',18,'2021-06-01','上海'),:-] (2,'李四',19,'2021-02-10','北京'),:-] (3,'王五',12,'2021-06-01','天津'),:-] (1,'马六',10,'2021-06-18','上海'),:-] (5,'田七',22,'2021-02-09','广州');#查看表中的数据node1 :) select * from t_mt;SELECT *FROM t_mt┌─id─┬─name─┬─age─┬───birthday─┬─location─┐│ 1 │ 马六 │ 10 │ 2021-06-18 │ 上海 ││ 1 │ 张三 │ 18 │ 2021-06-01 │ 上海 ││ 3 │ 王五 │ 12 │ 2021-06-01 │ 天津 │└───┴──────┴─────┴──────────┴─────────┘┌─id─┬─name─┬─age─┬───birthday─┬─location─┐│ 2 │ 李四 │ 19 │ 2021-02-10 │ 北京 ││ 5 │ 田七 │ 22 │ 2021-02-09 │ 广州 │└────┴─────┴─────┴───────────┴────────┘5 rows in set. Elapsed: 0.006 sec.
继续向表 t_mt中插入以下数据条目:
#向表t_mt中继续插入以下数据node1 :) insert into t_mt values (1,'赵八',11,'2021-06-08','北京'),:-] (2,'李九',19,'2021-02-10','天津'),:-] (3,'郑十',12,'2021-07-01','北京');#继续查询表 t_mt中的数据node1 :) select * from t_mt;SELECT *FROM t_mt┌─id─┬─name─┬─age─┬───birthday─┬─location─┐│ 1 │ 马六 │ 10 │ 2021-06-18 │ 上海 ││ 1 │ 张三 │ 18 │ 2021-06-01 │ 上海 ││ 3 │ 王五 │ 12 │ 2021-06-01 │ 天津 │└────┴──────┴─────┴────────────┴──────────┘┌─id─┬─name─┬─age─┬───birthday─┬─location─┐│ 2 │ 李四 │ 19 │ 2021-02-10 │ 北京 ││ 5 │ 田七 │ 22 │ 2021-02-09 │ 广州 │└────┴──────┴─────┴────────────┴──────────┘┌─id─┬─name─┬─age─┬───birthday─┬─location─┐│ 1 │ 赵八 │ 11 │ 2021-06-08 │ 北京 ││ 7 │ 郑十 │ 17 │ 2021-06-01 │ 北京 │└────┴──────┴─────┴────────────┴──────────┘┌─id─┬─name─┬─age─┬───birthday─┬─location─┐│ 6 │ 李九 │ 19 │ 2021-02-10 │ 天津 │└────┴──────┴─────┴────────────┴──────────┘8 rows in set. Elapsed: 0.008 sec.
可以看到新插入的数据新生成了数据块,实际上这里在底层对应新的分区文件片段,那么为什么新插入的数据没有根据日期和之前的数据放入同一个分区文件呢?MergeTree引擎会在插入数据15分钟左右,将同一个分区的各个分区文件片段合并成一整个分区文件。这里也可以手动执行OPTIMIZE 语句手动触发合并。
4. 示例二
#手动触发表t_mt 的分区合并node1 :) optimize table t_mt partition '202102';node1 :) optimize table t_mt partition '202106';注意:以上optimize 操作,也可以直接写 optimize table t_mt, 每次执行合并一个分区,如果有多个分区需要执行多次。如果想一次合并所有分区,也可以写成 optimize table t_mt final;#查看表 t_mt表中的数据,按照相同的分区进行了合并。node1 :) select * from t_mt;SELECT *FROM t_mt┌─id─┬─name─┬─age─┬───birthday─┬─location─┐│ 1 │ 马六 │ 10 │ 2021-06-18 │ 上海 ││ 1 │ 赵八 │ 11 │ 2021-06-08 │ 北京 ││ 1 │ 张三 │ 18 │ 2021-06-01 │ 上海 ││ 3 │ 王五 │ 12 │ 2021-06-01 │ 天津 ││ 7 │ 郑十 │ 17 │ 2021-06-01 │ 北京 │└────┴──────┴─────┴────────────┴──────────┘┌─id─┬─name─┬─age─┬───birthday─┬─location─┐│ 2 │ 李四 │ 19 │ 2021-02-10 │ 北京 ││ 5 │ 田七 │ 22 │ 2021-02-09 │ 广州 ││ 6 │ 李九 │ 19 │ 2021-02-10 │ 天津 │└────┴──────┴─────┴────────────┴──────────┘8 rows in set. Elapsed: 0.004 sec.注意:MergeTree引擎表中主键并不用于去重,而是用于索引,加快查询速度。
👨💻如需博文中的资料请私信博主。