Clickhouse原理与应用实践(四)表引擎以及查询

1、MergeTree

1.1 TTL

  • 存在列级TTL、表级TTL。 TTL create_time + INTERVAL 10 SECOND
  • 写入数据时,会以数据分区为单位,在每个分区目录内生成一个名为ttl.txt的文件。
  • 每当写入一批数据时,都会基于INTERVAL计算结果为分区生成ttl.txt。
  • 只有在MergeTree合并分区时,才触发TTL过期逻辑。
  • 规则是找过期早,合并次数多的。

1.2 多路径存储

  • 支持以数据分区为最小移动单元,将分区目录写入多块磁盘目录。
  • JBOD 服务器挂在多块磁盘,没有RAID,每执行一次INSERT或者MERGE,所产生的新分区会轮训写入各个磁盘。
  • HOT/COLD。数据在写入之初回在HOT区域创建并保存,当分区数据大小累积到阈值,会自行移动到COLD区域。

2、ReplacingMergeTree

  • MergeTree的主键没有唯一键约束。ReplacingMergeTree能够在合并分区时删除重复数据。
  • 以ORDER BY 键为准,不是PRIMARY KEY。以分区为单位删除重复数据。
  • 如果有ver则保留ver最大的,否则保留最后一行。

3、SummingMergeTree

  • 在只关心数据汇总结果,不关心明细数据时。
  • 能够在合并分区时按照预先定义的条件聚合汇总数据。
  • 通常只有在使用SummingMergeTree AggregatingMergeTree时,ORDER BY和PRIMRY KEY不一样,这些引擎都是按照ORDER BY聚合,主键与聚合条件定义分离,为修改聚合条件留下空间。
  • 但是PRIMARY KEY必须是ORDER BY前缀。
  • 如果有嵌套类型,会按嵌套类型中的第一个字段作为聚合条件。
  • 只在合并分区时触发。

4、AggregatingMergeTree

  • 能够以二进制存储中间状态结果
  • code和value是聚合字段,语义等同于UNIQ(code) SUM(value)
CREATE TABLE xx (
  id String,
  city String,
  code AggregateFunction(uniq, String),
  value AggregateFunction(sum, UInt32),
  create_time DateTime
) ENGINE = AggregatingMergeTree()
PARTITION BY
ORDER BY
  • 插入时要写uniqueState('') sumState('')
  • 查询时要写uniqueMerge(code) sumMerge(value)
  • 常结合物化视图使用,在底层有一个MergeTree更新就更方便。
  • 也是只有分区才会触发聚合逻辑,聚合key是ORDER BY制定的。

5、CollapsingMergeTree

  • 以增代删的思路,支持行级数据修改和删除的表引擎。它通过定义一个sign标记位字段,记录数据行状态。如果是-1就是需要被删除的,同一分区内1和-1的sign会抵消。
CollapsingMergeTree
  • 如果-1和1一样多,并且最后一行是1,则保留第一行-1和最后一行1
  • 如果-1和1一样多,并且最后一行是-1则都不保留。

6、VersionedCollapsingMergeTree

CREATE TABLE ver_coll (
  id String,
  code Int32,
  ver UInt
) ENGINE = VersionedCollapsingMergeTree(ver)
  • 会自动将ver作为排序条件并增加到ORDER BY的末端。

7、各种MergeTree之间的关系总结

  • 其他6个变种表引擎的Merge合并逻辑,全部是建立在MergeTree基础之上的,且均继承于MergingSortedBlockInputStream
  • 区分知识Merge逻辑,所以特殊功能只在Merge合并时才会触发。
逻辑区分
ReplicatedMergeTree
  • 通过Zookeeper消息日志广播,实现副本实例之间的数据同步功能。

8、外部存储类型

  • 直接从其他存储系统读取数据,表引擎只负责元数据管理和数据查询,通常不负责数据写入
  • 包括HDFS、Mysql、JDBC、Kafka、File等类型。JDBC表引擎无法单独完成所有工作,需要依赖名为clickhouse-jdbc-bridge的查询代理服务。File表引擎的数据文件智能保存在config.xml配置中由path制定的路径下。

9、 内存

  • Memory,重启就会消失
  • Set,首先会被写内存,然后被同步到磁盘。不能直接使用select查,只能简介作为IN查询的右侧条件被查询使用。带有去重能力。
  • Join,和set类似,但是可以作为Join的链接表,支持ALL ANY ASOF三种类型。ALL会忽略join_key的重复。
CREATE TABLE id_join(
  id UInt8,
  price UInt32,
  time Datetime
) ENGINE = Join(ANY, LEFT, id)

SELECT id,name,price from xx LEFT JOIN id_join USING(id)
  • Buffer,不是为了查询而设计的,是用来充当缓冲区的,比如写入速度很大的时候。
Buffer

10、 日志

  • 适用数据量很小、一次写入多次查询的场景。
  • 均不支持索引、分区等高级特性;不支持并发读写,当针对一张日志表写入时,针对这张表的查询会被阻塞。
  • Log,有[column].bin文件 __marks.mrk sizes.json几个文件,各列独立存储,可以并行查询、能够按列按需读取

11、 其他类型

  • Merge,负责合并多个查询的结果集。比如有的表是按年存的,可以用一个merge替代多张表
  • Live View 不是表引擎,类似事件监听器。能够将一条SQL查询结果作为监控目标,当目标数据增加时,可以发出相应。CREATE LIVE VIEW lv AS SELECT count(*) FROM xxx会按递增版本显示监听的内容。
  • Null,如果使用物化视图,不希望保留源表数据,可以把源表设置成null。

12、查询

12.1 SAMPLE

  • 幂等设计,数据不发生变化,相同规则获取相同数据。
  • SAMPLE BY声明的表达式必须同时包含在主键的声明内,Sample Key必须是Int类型

12.2 Array Join

  • 将一个数组展开为多行 类似lateval view + explode
  • 对多个数组字段进行Array Join,逻辑是按行合并不是产生笛卡尔积。如果多个数组同时Array Join,同一行里的数组长度需要一样。

12.3 Join

  • ALL就是正常逻辑下理解的Join
  • ANY,如果左表一行,右表多个匹配,只返回第一个。
  • ASOF,模糊链接,asof_column必须是整型、浮点型和日期这类有序序列的数据类型。
SELECT xx  FROM a ASOF INNER JOIN b ON a.id = b.id AND a.time = b.time
// 等同于a.time > b.time
  • 应遵循左大右小的原则,目前没有缓存支持。

12.4 GRPOUP BY

  • WITH ROLLUP
  • WITH CUBE
  • WITH TOTALS 基于聚合函数对所有数据进行统计。但是只聚合在对应的group by粒度。

12.5 HAVING

  • 在clickhouse里 嵌套WHERE效率会更高,因为会有谓词下推。
  • HAVING是在聚合之后增加了filter

12.6 LIMIT BY

  • 能够按照指定分组,最多返回前n行数据

13、查询计划

  • clickhouse-client -h localhost --send_logs_level=trace <<< '执行语句' > /dev/null
查询计划
  • Key condition
  • MinMax index condition
  • 分区目录数
  • 扫描数据行数
  • 消耗多少内存
  • 具体的执行计划树。

你可能感兴趣的:(Clickhouse原理与应用实践(四)表引擎以及查询)