Clickhouse - MergeTree原理

MergeTree引擎以及隶属于MergeTree引擎族的所有引擎是Clickhouse表引擎中最重要, 最强大的引擎.

MergeTree引擎族中的引擎被设计用于将大量数据写入表中. 这些数据被快速的写入每个表的每个part, 然后在Clickhouse底层会进行多个parts的合并(merge). 这种形式的处理比在插入过程中不断重写存储中的数据要高效得多.

主要的功能点:

  • 存储按主键(primary key)排序的数据.

    这允许用户可以创建一个小型的稀疏索引, 有利于更快的在表中找到索要的数据.

  • 如果partitioning key被设置, 分片(partitions)可以被使用.

    Clickhouse支持某些带分区的操作, 对于同一份数据进行处理, 带有分区的操作会比一般操作更有效. 当在查询语句中指定了分区后, Clickhouse会根据分区信息来进行数据的切分, 这样极大程度上提升了查询的性能.

  • 数据副本机制支持(Replication)

    ReplicatedMergeTree并引擎提供了数据副本机制.

  • 支持数据采样

    如果必要, 可以在表中设置数据采样方式.

1. 创建表

1.1. 建表语句

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, ...]

1.2. 参数说明

  • ENGINE: 指定该表所使用的的引擎. 如果引擎需要一些具体的参数, 需要进行相应的设置, MergeTree引擎不需要, 例如ReplicatedMergeTree:

    ENGINE=ReplicatedMergeTree('/clickhouse/tables/#_tenant_id_#/#__appname__#/#_at_date_#/{shard}/hits', '{replica}')
  • ORDER BY : 按指定字段进行排序

    支持设置的值为元组(一个列名或任意多字段表达式), 例如:

    ORDER BY (CounterID, EventDate)

    如果创建表的时候, 没有使用PRIMARY KEY修饰词来显式指定主键, 那么Clickhouse会将ORDER BY指定的字段作为主键处理.

    如果该表不需要排序, 可以使用ORDER BY tuple()语法.

  • PARTITION BY: 指定分区字段, 可选

    分区字段一般是一个Date类型或者DateTime类型的字段. 如果想按照月进行分区, 可以使用toYYYYMM(date_column)表达式, 那么分区字段的格式就是YYYYMM.

  • PAIMARY KEY: 主键, 可选

    默认情况下, 在Clickhouse中主键都是和排序字段(ORDER BY 子句指定字段)是一致的, 所以在大多数情况下, 不需要单独指定主键. 如果需要两者不一致, 详情可见differs from the sorting key.

  • SAMPLE BY: 取样表达式, 可选

    如果使用了SAMPLE BY子句, 那么SAMPLE BY指定的字段必须是主键(或排序字段)所包含的字段. 例如:

    SAMPLE BY intHash32(USERID)
    ORDER BY (CounterID, EventDate, intHash32(UserID))
  • TTL: 一些被指定的规则, 涉及存储数据行的存储时长, 以及确定数据parts的自动移除逻辑. 可选

    TTL表达式必须包含一个Date类型或者DateTime类型的字段作为一个结果值, 例如:

    TTL date + INTERVAL 1 DAY

    这种类型的规则DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'指定了当表达式条件被满足时对数据parts处理的操作: 删除过期的行, 移除数据parts(如果该数据parts中所有的行都满足条件)到指定的位置TO DISK 'XXX'.规则的默认类型是DELETE. 可以指定多个规则组成一条表达式, 但是DELETE规则不成超过一条.

    查看更多细节: TTL for columns and tables.

  • SETTINGS: 设置MergeTree引擎的附加的参数, 可选

    • index_graularity

      索引标记之间的最大数据行数. 默认值: 8192.

    • index_graularity_bytes

      数据颗粒的最大大小, 单位bytes, 默认值: 10MB. 若要仅按行数限制颗粒大小, 请设置为0(不推荐).

    • min_index_granularity_bytes

      数据颗粒的最小大小, 单位bytes, 默认值: 1024b. 该值是为了防止意外创建index_graularity_bytes值很低的表.

    • enable_mixed_granularity_parts

      同样是设置数据颗粒的最大大小, 该参数用于过渡取代index_graularity_bytes. 在v19.11版本前, 只有index_granularity用于控制颗粒大小.当查询数据涉及到大量的行(几十或几百兆)时, index_granularity_bytes参数提高了Clickhouse的性能. 如果你的表拥有大量的行时, 可以为表启用这个参数来提高查询的性能.

    • use_minimalistic_part_header_in_zookeeper

      在Zookeeper中数据parts_headers存储的方式. 如果设置为1, 则Zookeeper中存储的数据较少, 具体可以参考setting description.

    • min_merge_bytes_to_use_direct_io

      使用直接I/O访问存储磁盘所需的merge操作的最小数据量. merge数据parts时, Clickhouse会计算所有要合并的数据的总存储空间, 如果超过min_merge_bytes_to_use_direct_io设定的值, Clickhouse会使用直接I/O接口(O_DIRECT选项)读取和写入数据到磁盘. 如果设置为0, 则直接I/O被禁用, 默认值: 10M.

    • merge_with_ttl_timeout

      重复合并TTL的最小延迟时间, 单位秒, 默认值: 1 day.

    • write_final_mark

      启用或禁用在数据部分的末尾(最后一个字节之后)写入最后的索引标记. 默认值: 1, 不要关闭.

    • merge_max_block_size

      合并操作时, 每个块的最大行数, 默认值: 8192.

    • storage_policy

      存储策略, 详见Using Multiple Block Devices for Data Storage.

    • min_bytes_for_wide_part, min_rows_for_wide_part

      数据部分中可存储为Wide格式的最小字节数/行数. 可以设置这些设置中的一个, 两个或全部.

1.3. 样例说明

ENGINE MergeTree()
PARTITION BY toYYYYMM(EventDate)
ORDER BY (CounterID, EventDate, intHash32(UserID))
SAMPLE BY intHash32(UserID)
SETTINGS index_granularity=8192

在这个样例中, 设置了按月份进行分区.

同时设置了一个表达式 -> 按用户ID进行Hash采样. 这样就可以为每个CounterID和EventDate伪随机化(pseudorandomize)表中的数据. 如果你在选择数据时定义了一个SAMPLE子句, Clickhouse将会为用户的子集返回一个均匀的伪随机化的数据样本.

index_granularity设置可以省略, 因为8192是默认值.

2. 数据存储

一个表由按主键排序的数据parts组成.

当在表中插入数据时, 会创建单独的数据parts, 并对每个数据parts按主键进行字典排序. 例如, 如果主键是(CounterID, Date), 则该部分的数据会按照CounterID排序, 在每个CounterID内, 再按照Date排序.

属于不同分片的数据会被分隔成不同的part. 在Clickhouse底层, ck合并数据parts成为更有效的存储结构. 属于不同分片的parts不会被merge. Merge机制并不能保证所有具有相同主键的行都在同一个数据parts.

数据parts可以用宽(Wide)或者紧凑(Compact)格式来存储. 在Wide格式中, 每一列都会被存储在磁盘的一个单独的文件中, 在Compact格式中, 所有的列都会被存在在同一个文件中. Compact格式可以用来提高小规模和频繁插入的性能(涉及到写入到更少的文件中).

数据存储格式有表引擎的min_bytes_for_wide_partmin_rows_for_wide_part参数控制. 如果数据parts的字节数小于相应的设置项, 则该部分以Compact格式存储, 反之以Wide格式存储. 如果这两个参数未被设置, 将会默认以Wide格式存储.

每个数据part在逻辑上被划分成颗粒(granule). 一个颗粒是Clickhouse在读取选中数据时, 最小的不可分割的数据集单位. Clickhouse不会拆分行或者字段值, 所以每个颗粒总是包含整数单位的行. 颗粒的第一行是用该行的主键值进行标记的. 对于每个数据part来说, Clickhouse都会创建一个索引文件来存储这些标记(mark). 对于每一列而言, 无论它是否是主键, Clickhouse都会存储相同的标记. 这些标记可以帮助查询的时候直接在列文件中找到数据.

颗粒的大小收到表引擎index_granularityindex_granularity_bytes参数的限制. 根据行的大小, 一个颗粒中的行数在[1, index_granularity]范围内. 如果单行的大小大于设置值, 那么颗粒的大小可以超过index_granularity_bytes. 在这种情况下, 颗粒的大小等于行的大小.

Clickhouse - MergeTree原理的更多相关文章

  1. LSM 树详解

    LSM树(Log Structured Merged Tree)的名字往往给人一个错误的印象, 实际上LSM树并没有严格的树状结构. LSM 树的思想是使用顺序写代替随机写来提高写性能,与此同时会略微 ...

  2. clickhouse核心引擎MergeTree子引擎

    在clickhouse使用过程中,针对数据量和查询场景,MergeTree是最常用也是较为合适的表引擎.针对特定的业务,MergeTree的子引擎可以针对不同的业务而定,但都基于MergeTree引擎 ...

  3. Clickhouse的MergeTree表引擎存储结构

    MergeTree存储的文件结构 一张数据表被分成几个data part,每个data part对应文件系统中的一个目录.通过以下SQL可以查询data parts的信息. select table, ...

  4. ClickHouse(10)ClickHouse合并树MergeTree家族表引擎之ReplacingMergeTree详细解析

    目录 建表语法 数据处理策略 资料分享 参考文章 MergeTree拥有主键,但是它的主键却没有唯一键的约束.这意味着即便多行数据的主键相同,它们还是能够被正常写入.在某些使用场合,用户并不希望数据表 ...

  5. 列式数据库~clickhouse 底层存储原理

    简介:今天介绍列式数据库的一些基本原理 一  数据目录 Data目录 数据存储目录,数据按照part分成多个文件夹,每个文件夹下存储相应数据和对应的元信息文件 Metadata 表定义语句,存储所有表 ...

  6. Clickhouse中的预聚合引擎

    作者: LemonNan 原文地址: https://mp.weixin.qq.com/s/qXlmGTr4C1NjodXeM4V9pA 注: 转载需注明作者及原文地址 介绍 本文将介绍 Clickh ...

  7. 浅淡 Apache Kylin 与 ClickHouse 的对比

    作者简介 周耀,Kyligence 解决方案架构师,Apache Kylin.Apache Superset Contributor. Apache Kylin 和 ClickHouse 都是目前市场 ...

  8. 浅谈MySQL、Hadoop、BigTable、Clickhouse数据读写机制

    个人理解,欢迎指正 数据库 引擎 写数据 读数据 补充 MySql InnoDB:支持事务,高速读写性能一般 Myisam:不支持事务,高速读写性能好 以InnoDB更新一条记录为例 1.B+Tree ...

  9. clickhouse的使用和技巧,仅个人

    centos 安装clickhouse curl -s https://packagecloud.io/install/repositories/altinity/clickhouse/script. ...

随机推荐

  1. 【解决了一个小问题】golang build中因为缓存文件损坏导致的编译错误

    编译的过程中出现了一个吓人的错误: GOROOT=C:\Go #gosetup GOPATH=C:\Users\ahfuzhang\go #gosetup C:\Go\bin\go.exe mod t ...

  2. 论文翻译:2021_DeepFilterNet: A Low Complexity Speech Enhancement Framework for Full-Band Audio based on Deep Filtering

    论文地址:DeepFilterNet:基于深度滤波的全频带音频低复杂度语音增强框架 论文代码:https://github.com/ Rikorose/DeepFilterNet 引用:Schröte ...

  3. 常见Web服务器

    常见Web服务器

  4. jetson-nano opencv基础使用

    前言: jetson nano前一篇给大家介绍了学习的一些思路和资料,今天继续给大家分享一篇在jetson nano使用opencv的文章. OpenCV的全称是Open Source Compute ...

  5. postgresql dba常用sql查询语句

    查看帮助命令 DB=# help --总的帮助 DB=# \h --SQL commands级的帮助 DB=# \? --psql commands级的帮助 \dn[S+] [PATTERN],其中[ ...

  6. 字节跳动Web Infra发起 Modern.js 开源项目,打造现代 Web 工程体系

    10 月 27 日举办的稀土开发者大会上,字节跳动 Web Infra 正式发起 Modern.js 开源项目,希望推动现代 Web 开发范式的普及,发展完整的现代 Web 工程体系,突破应用开发效率 ...

  7. 如何加载本地下载下来的BERT模型,pytorch踩坑!!

    近期做实验频繁用到BERT,所以想着下载下来使用,结果各种问题,网上一搜也是简单一句:xxx.from_pretrained("改为自己的路径") 我只想说,大坑!!! 废话不多说 ...

  8. 学习Java第10天

    今天所作的工作: 1.线程 2.网络通信 明天工作安排: 做点教材后的案例,复习所学内容 总结一下,10天的时间,看完了Java从入门到精通,只能说是看完了,这里加一个表情笑哭,应该算是知道Java的 ...

  9. GitHubPages的域名解析信息

    github目录下CNAME修改

  10. k8s基本概念,资源对象

    kubernetes里的master指的是集群控制节点 master负责是整个集群的管理和控制 kubernetes3大进程 API server 增删改查操作的关键入口 controller man ...