《clickhouse》笔记(一)

202 阅读4分钟

建表

CREATE TABLE [IF NOT EXISTS] [db_name.]table_name(
    name1 type [DEFAULT|MATERIALIZED|ALIAS expr],
    name2 type [DEFAULT|MATERIALIZED|ALIAS expr],
    ......
) ENGINE = MergeTree()
[PARTITION BY expr]
ORDER BY expr
[PRIMARY KEY expr]
[SAMPLE BY expr]
[SETTINGS name1=value1, name2=value2, ......]

说明:

  • 1) PARTITON BY:选填,表示分区键,用于指定表数据以何种标准进行分区。分区键既可以是单个字段、也可以通过元组的形式指定多个字段,同时也支持使用列表达式。如果不支持分区键,那么 ClickHouse 会生成一个名称为 all 的分区,合理地使用分区可以有效的减少查询时数据量。最常见的莫过于按照时间分区了,数据量非常大的时候可以按照天来分区,一天一个分区,这样查找某一天的数据时直接从指定分区中查找即可。**
  • 2)ORDER BY:必填,表示排序键,用于指定在一个分区内,数据以何种标准进行排序。排序键既可以是单个字段,例如 ORDER BY CounterID,也可以是通过元组声明的多个字段,例如 ORDER BY (CounterID, EventDate)。如果是多个字段,那么会先按照第一个字段排序,如果第一个字段中有相同的值,那么再按照第二个字段排序,依次类推。总之在每个分区内,数据是按照分区键排好序的,但多个分区之间就没有这种关系了。**
  • 3)PRIMARY KEY:选填,表示主键,声明之后会依次按照主键字段生成一级索引,用于加速表查询。如果不指定,那么主键默认和排序键相同,所以通常直接使用 ORDER BY 代为指定主键,无须使用 PRIMARY KEY 声明。所以一般情况下,在每个分区内,数据与一级索引以相同的规则升序排列(因为数据是按照排序键排列的,而一级索引也是按排序键、也就是主键进行排列的)。和其它关系型数据库不同,MergeTree 允许主键有重复数据(可以通过 ReplacingMergeTree 实现去重)。**
  • 4)SAMPLE KEY:选填,抽样表达式。用于声明数据以何种标准进行采样,**
  • 5)settings 额外参数 选填 例如SETTINGS index_granularity=8192, min_compress_block_size=6536

MergeTree数据结构

  1. 数据文件

    table
      |----partition_1 //分区目录
      |        |---checksums.txt //校验文件,保存了余下各类文件(primary.txt、count.txt 等等)的 size 大小以及哈希值,用于快速校验文件的完整性和正确性
      |        |---columns.txt // 列信息文件,使用明文格式存储列字段信息
      |        |---count.txt // 计数文件,使用明文格式存储当前分区下的数据总数
      |        |---primary.idx // 一级索引文件,使用二进制格式存储,用于存储稀疏索引,(通过 ORDER BY 或 PRIMARY KEY)。借助稀疏索引,在查询数据时能够排除主键条件范围之外的数据文件,从而有效减少数据扫描范围,加速查询速度
      |        |---data.bin // 数据文件 。在老版本中每一个列字段都有自己独立的 .bin 数据文件,并以列字段命名,但是在新版本中只有一个 data.bin,也就是合并在一起了;但是我看按很多文章中都是独立的,不影响理解;
      |        |---data.mrk // 标记文件,,使用二进制格式存储,标记文件中保存了 data.bin 文件中数据的偏移量信息,并且标记文件与稀疏索引对齐,因此 MergeTree 通过标记文件建立了稀疏索引(primary.idx)与数据文件(data.bin)之间的映射关系 
      |        |---data.mrk3// 如果使用了自适应大小的索引间隔则使用mrk3
      |        |---partition.dat // 如果使用了分区键,例如上面的 PARTITION BY toYYYYMM(JoinTime),则会额外生成 partition.dat 与 minmax_JoinTime.idx 索引文件,它们均使用二进制格式存储。partition.dat 用于保存当前分区下分区表达式最终生成的值,而 minmax_[Column].idx 则负责记录当前分区下分区字段对应原始数据的最小值和最大值。
      |        |---minmax_[Column].idx
      |        |---skp_idx_[IndexName].idx // 如果在建表语句中指定了二级索引(跳数索引),则会额外生成相应的二级索引文件与标记文件,它们同样使用二进制存储; 
      |        |---skp_idx_[IndexName].mrk3
      |
      |----partition_2
      |...
      |----partition_n
  • 主键索引

    • 为什么不是B(+)-树,1):额外的磁盘和内存开销, 2)向表中添加新行和向索引中添加条目时更高的插入成本(有时还需要重新平衡B-Tree)。; 好处是快速定位主键

    • clickhouse中不是为每一行创建索引,而是为一组数据行(称为颗粒(granule))构建一个索引条目。与直接定位单个行(如基于B-Tree的索引)不同,稀疏主索引允许它快速(通过对索引项进行二分查找)识别可能匹配查询的行组。

    • 颗粒对应主索引

image-20240705175252177.png

  • 跳数索引,

    • 1.minmax一种类型简单的说就是只保存块内的最大值和最小值;
    • 2.set 类型,指定块的最大值,有点类似于基数排序里面的基数
    • 3.bloomfilter

    Reference: clickhouse.com/docs/zh/gui…